玄关求调启发式合并
查看原帖
玄关求调启发式合并
804607
rainygame楼主2024/3/23 12:59
#include <bits/stdc++.h>
using namespace std;
#define MAXN 1000001

int n, q;
int b[MAXN];
list<int> a[MAXN];
set<pair<int, int>> st[MAXN];
map<int, int> g[MAXN];

void add(int ind, int x){
    a[ind].push_back(x);
    if (g[ind].count(x)) st[ind].erase({g[ind][x], x});
    st[ind].insert({++g[ind][x], x});
}

void del(int ind){
    int x(a[ind].back());
    st[ind].erase({g[ind][x], x});
    if (g[ind][x] > 1) st[ind].insert({--g[ind][x], x});
    if (!g[ind][x]) g[ind].erase(x);
    a[ind].pop_back();
}

void merge(int x, int y, int z){
    if (a[x].empty()){
        swap(a[z], a[y]);
        swap(st[z], st[y]);
        swap(g[z], g[y]);
        return;
    }
    if (a[y].empty()){
        swap(a[z], a[x]);
        swap(st[z], st[x]);
        swap(g[z], g[x]);
        return;
    }

    if (a[x].size() > a[y].size()){
        swap(a[x], a[z]);
        a[z].splice(a[z].end(), a[y]);
        swap(x, y);
    }else{
        swap(a[x], a[z]);
        a[z].splice(a[z].end(), a[y]);
    }
    for (auto i: st[x]){
        if (g[y][i.second]) st[y].erase({g[y][i.second], i.second});
        st[y].insert({g[y][i.second]+=i.first, i.second});
    }
    swap(st[z], st[y]);
    swap(g[z], g[y]);
}

bool check(int l, int r, int x){
    int res(0), siz(0);
    for (int i(l); i<=r; ++i){
        res += g[b[i]][x];
        siz += a[b[i]].size();
    }
    return (res<<1) > siz;
}

int solve(int l, int r){
    if (l == r){
        if (st[b[l]].empty() || (st[b[l]].rbegin()->first<<1) <= a[b[l]].size()) return -1;
        return st[b[l]].rbegin()->second;
    }

    int mid((l+r)>>1), res1(solve(l, mid)), res2(solve(mid+1, r));
    if ((~res1) && check(l, r, res1)) return res1;
    if ((~res2) && check(l, r, res2)) return res2;
    return -1;
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> q;
    for (int i(1), l; i<=n; ++i){
        cin >> l;
        for (int x; l; --l){
            cin >> x;
            add(i, x);
        }
    }

    for (int opt, x, y, z; q; --q){
        cin >> opt >> x;
        if (opt == 1){
            cin >> y;
            add(x, y);
        }else if (opt == 2) del(x);
        else if (opt == 3){
            for (int i(1); i<=x; cin >> b[i++]);
            cout << solve(1, x) << '\n';
        }else{
            cin >> y >> z;
            merge(x, y, z);
        }
    }

    return 0;
}

真的看不出来有什么问题了,x1/x2 的 empty 也判了。

2024/3/23 12:59
加载中...