poj2985 The k-th Largest Group

来源:互联网 发布:中国网络电影演员 编辑:程序博客网 时间:2024/06/01 23:40

题面在这里
题目大意:
有n个集合,每个集合有一个互不相同的元素。现在有两种操作:合并x, y所在的集合;询问第k大的集合元素个数。

做法:
并查集+平衡树。平衡树里维护每个集合的元素个数。

/*************************************************************    Problem: poj 2985 The k-th Largest Group    User: fengyuan    Language: C++    Result: Accepted    Time: 735 ms    Memory: 1.8 MB    Submit_Time: 2017-12-09 15:47:40*************************************************************/#include<cstdio>#include<cstring>#define rep(i, x, y) for (int i = (x); i <= (y); i ++)#define down(i, x, y) for (int i = (x); i >= (y); i --)#define mid ((l+r)/2)#define lc (o<<1)#define rc (o<<1|1)#define pb push_back#define mp make_pair#define PII pair<int, int>#define F first#define S second#define B begin()#define E end()using namespace std;typedef long long LL;//headconst int N = 400010;int n, m, rt, tot;int num[N], f[N], sz[N], cnt[N], data[N], fa[N], ch[N][2];inline int getFa(int v){ return f[v] == v ? v : f[v] = getFa(f[v]); }inline void pushup(int x){ sz[x] = (ch[x][0]?sz[ch[x][0]]:0) + (ch[x][1]?sz[ch[x][1]]:0) + cnt[x]; }inline void clear(int x){ fa[x] = ch[x][0] = ch[x][1] = data[x] = sz[x] = cnt[x] = 0; }inline void rot(int x){    int y = fa[x], z = fa[y];    int ff = (ch[y][1] == x);    ch[y][ff] = ch[x][ff^1]; if (ch[x][ff^1]) fa[ch[x][ff^1]] = y;    fa[x] = z; if (z) ch[z][(ch[z][1] == y)] = x;    fa[y] = x; ch[x][ff^1] = y;    pushup(y); pushup(x);}inline void splay(int x, int top){    while (fa[x] != top){        int y = fa[x], z = fa[y];        if (z != top) rot(((ch[z][0] == y) == (ch[y][0] == x)) ? y : x);        rot(x);    } if (!top) rt = x;}inline int find(int v){    int x = rt;    while (x){        if (data[x] == v){ splay(x, 0); return x; }        x = ch[x][v > data[x]];    }}inline int pre(int x){ x = ch[x][0]; while (ch[x][1]) x = ch[x][1]; return x; }inline void insert(int v){    int x = rt;    if (!rt){        x = rt = ++ tot;        data[x] = v; sz[x] = cnt[x] = 1;        fa[x] = ch[x][0] = ch[x][1] = 0;        return;    }    while (x){        sz[x] ++; if (v == data[x]){ cnt[x] ++; break; }        int &y = ch[x][v > data[x]];        if (!y){            y = ++ tot;            data[y] = v; sz[y] = cnt[y] = 1;            fa[y] = x; ch[y][0] = ch[y][1] = 0;            x = y; break;        } x = y;    } splay(x, 0);}inline void del(int v){    int x = find(v);    if (cnt[x] > 1){ cnt[x] --; pushup(x); return; }    if (!ch[x][0] && !ch[x][1]){ clear(rt); rt = tot = 0; return; }    if (!ch[x][0]){ rt = ch[x][1]; fa[rt] = 0; return; }    if (!ch[x][1]){ rt = ch[x][0]; fa[rt] = 0; return; }    int p = pre(x), rtt = rt; splay(p, 0);    ch[rt][1] = ch[rtt][1]; fa[ch[rtt][1]] = rt;    clear(rtt); pushup(rt);}inline int kth(int k){    int x = rt;    while (x){        if (sz[ch[x][0]] < k && sz[ch[x][0]]+cnt[x] >= k) return data[x];        if (sz[ch[x][0]] >= k) x = ch[x][0];        else k -= sz[ch[x][0]]+cnt[x], x = ch[x][1];    }}int main(){    scanf("%d%d", &n, &m);    rep(i, 1, n) num[i] = 1, f[i] = i, insert(1);    while (m --){        int opt, x, y, fx, fy;        scanf("%d", &opt);        if (!opt){            scanf("%d%d", &x, &y);            fx = getFa(x); fy = getFa(y);            if (fx != fy){                f[fx] = fy;                del(num[fx]); del(num[fy]);                num[fy] += num[fx];                num[fx] = 0;                insert(num[fy]);                n --;            }        } else {            scanf("%d", &x);            printf("%d\n", kth(n-x+1));        }    }    return 0;}
原创粉丝点击