poj 2985 The k-th Largest Group (并查集x全局动态第k大)

来源:互联网 发布:梦幻西游物价软件 编辑:程序博客网 时间:2024/05/22 10:54

题意:
。。。
思路:
用一个数据结构来存所有树的大小,合并操作先消去旧的再插入新的大小。
可以用 treap, BIT等等。。
这里有个树状数组 O(logn) 查询的方法,没能看懂。。

const int N = 200000 + 5;typedef long long LL;namespace Treap {    static const int MaxNode = N;    int root, nodes, key[MaxNode], fix[MaxNode],    ch[MaxNode][2], cnt[MaxNode], siz[MaxNode];    void init() {        root = 0;        nodes = 1;        fix[0] = INT_MAX;        siz[0] = 0;    }    inline void update(int x) {        siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x];    }    void rot(int& x, int t) {        int y = ch[x][t];        ch[x][t] = ch[y][1^t];        ch[y][1^t] = x;        update(x);        update(y);        x = y;    }    void insert(int& x, int k) {        if ( x ) {            if ( key[x] == k ) {                ++ cnt[x];            } else {                int t = key[x] < k;                insert(ch[x][t], k);                if ( fix[ch[x][t]] < fix[x]  ) {                    rot(x, t);                }            }        } else {            x = nodes ++;            key[x] = k;            cnt[x] = 1;            fix[x] = rand();            ch[x][0] = ch[x][1] = 0;        }        update(x);    }    void erase(int& x, int k) {        if ( key[x] == k ) {            if ( cnt[x] > 1 ) {                -- cnt[x];            } else {                if ( !ch[x][0] && !ch[x][1] ) {                    x = 0;                    return;                } else {                    int t = fix[ch[x][0]] > fix[ch[x][1]];                    rot(x, t);                    erase(ch[x][1^t], k);                }            }        } else {            int t = key[x] < k;            if ( ch[x][t] ) erase(ch[x][t], k);        }        update(x);    }    int count(int x, int k) {        if ( x ) {            if ( key[x] == k )                return cnt[x];            else                return count( ch[x][key[x] < k], k );        } else            return 0;    }    int getKth(int x, int k) {        if ( k <= siz[ch[x][0]] )            return getKth(ch[x][0], k);        k -= siz[ch[x][0]] + cnt[x];        if ( k <= 0 )            return key[x];        if ( k <= siz[ch[x][1]] )            return getKth(ch[x][1], k);        else            throw runtime_error("this is no kth element");    }};namespace UF {    int pa[N], sz[N];    int Find(int x) { return x == pa[x] ? x : pa[x] = Find(pa[x]); }    void init(int n) {        Treap::init();        rep(i, 1, n) pa[i] = i, sz[i] = 1;        rep(i, 1, n) Treap::insert(Treap::root, 1);    }    void Union(int x, int y) {        int px = Find(x), py = Find(y);        if ( px != py ) {            Treap::erase(Treap::root, sz[px]);            Treap::erase(Treap::root, sz[py]);            sz[px] += sz[py];            pa[py] = px;            Treap::insert(Treap::root, sz[px]);            #if 0            cout << "after merge" << endl;            int tot = tree.siz[tree.root];            rep(i, 1, tot) cout << tree.getKth(tree.root, i) << ' '; cout << endl;            #endif // 1        }    }    int query(int k) {        int tot = Treap::siz[Treap::root];        try {            return Treap::getKth(Treap::root, tot + 1 - k);        } catch ( exception& e ) {            return 1;        }        //return tree.getKth(tree.root, tot + 1 - k);    }}int main() {#ifdef _LOCA_ENV_    freopen("input.in", "r", stdin);#endif // _LOCA_ENV    int n, m;    scanf("%d%d", &n, &m);    UF::init(n);    int op, x, y;    rep(i, 1, m) {        scanf("%d", &op);        if ( op == 0 ) {            scanf("%d%d", &x, &y);            //cout << "merge " << x << ' ' << y << endl;            UF::Union(x, y);        } else {            scanf("%d", &x);            //cout << "query " << x << endl;            printf("%d\n", UF::query(x));        }    }    return 0;}
1 0