您的位置:首页 > 其它

POJ2985 The k-th Largest Group(Splay)

2015-11-21 16:09 429 查看
有n组猫,m个操作。初始的时候每组猫有一只,有两种操作,可以把两组猫合并为一组,或者查询猫数第k多的组。

对于合并猫我们开一个并查集,检查那些已经在一个集合中的猫。首先在splay树中插入每组猫的数,当合并的时候,就从树中删去那两组猫,在插入它们的和。为了方便删除,在初始化的时候要插入0和n+1两个节点。

#include<cstdio>
#include<cctype>
#define MAXN 200010
void GET(int &t)
{
char c;
t = 0;
do{c = getchar();}while(!isdigit(c));
while(isdigit(c)){t = t*10+c-'0'; c = getchar();}
}
int fa[MAXN],sz[MAXN],cnt[MAXN],tot,root,ch[MAXN][2],v[MAXN],n,m,op,sat[MAXN],amount[MAXN];
int find(int x)
{
if(sat[x] == x) return sat[x];
else return sat[x] = find(sat[x]);
}
void update(int x)
{
sz[x] = sz[ch[x][0]]+sz[ch[x][1]]+cnt[x];
}
void rotate(int x)
{
int y = fa[x],z = fa[y],f = (ch[y][1]==x);
ch[y][f] = ch[x][!f];
if(ch[y][f]) fa[ch[y][f]] = y;
ch[x][!f] = y,fa[y] = x;
fa[x] = z;
if(z) ch[z][ch[z][1]==y] = x;
update(y);
}
void splay(int x,int goal)
{
for(int y; (y=fa[x])!=goal; rotate(x))
{
int z = fa[y];
if(z != goal)
{
if((ch[z][0]==y)==(ch[y][0]==x)) rotate(y);
else rotate(x);
}
}
if(goal == 0) root = x;
update(x);
}
void insert(int val)
{
int x = root,y = 0,f = 0;
while(x != 0)
{
if(v[x] == val) {++cnt[x]; break;}
f = v[x]<val;
y = x;
x = ch[x][f];
}
if(x == 0)
{
x = ++tot;
v[x] = val;
sz[x] = cnt[x] = 1;
fa[x] = y;
if(y) ch[y][f] = x;
}
splay(x,0);
}
int nxt(int val,bool flag)
{
int x = root,y = 0;
while(x != 0)
{
y = x;
if(v[x] == val) break;
x = ch[x][v[x]<val];
}
if((v[y]>val&&flag==1)||(v[y]<val&&flag==0)) return y;
splay(y,0);
int tmp = ch[y][flag];
while(ch[tmp][!flag])
tmp = ch[tmp][!flag];
return tmp;
}
void del(int val)
{
int x = nxt(val,0),y = nxt(val,1);
splay(x,0);
splay(y,x);
int z = ch[y][0];
if(z)
{
if(cnt[z] > 1)
{
cnt[z]--;
splay(z,0);
}
else
{
ch[y][0] = 0;
cnt[z] = 0;
splay(y,0);
}
}
}
int kth(int k)
{
int y = root,x;
if(k > sz[root]) return 0;
while(1)
{
x = ch[y][1];
if(sz[x]+cnt[y] < k)
{
k -= sz[x]+cnt[y];
y = ch[y][0];
}
else if(sz[x]>=k) y = x;
else return v[y];
}
}
int main()
{
GET(n);
GET(m);
insert(0);
insert(n+1);
for(int i = 1; i <= n; i++) sat[i] = i,insert(1),amount[i] = 1;
int a,b,c;
for(int i = 1; i <= m; i++)
{
GET(op);
if(op)
{
GET(a);
printf("%d\n",kth(a+1));
}
else
{
GET(a),GET(b);
a = find(a);
b = find(b);
if(a == b) continue;
del(amount[a]);
del(amount[b]);
c = amount[a]+amount[b];
sat[b] = a;
amount[a] = c;
amount[b] = c;
insert(c);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: