POJ2985 The k-th Largest Group(Splay)
2015-11-21 16:09
429 查看
有n组猫,m个操作。初始的时候每组猫有一只,有两种操作,可以把两组猫合并为一组,或者查询猫数第k多的组。
对于合并猫我们开一个并查集,检查那些已经在一个集合中的猫。首先在splay树中插入每组猫的数,当合并的时候,就从树中删去那两组猫,在插入它们的和。为了方便删除,在初始化的时候要插入0和n+1两个节点。
对于合并猫我们开一个并查集,检查那些已经在一个集合中的猫。首先在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); } } }
相关文章推荐
- 斐波那契首项 BAPC2014 I&&HUNNU11589:Interesting Integers
- Android Studio配置教程
- zabbix搭建与基本配置
- nginx多站点配置
- 关闭error, forbidden warning
- 浅谈在三级城市如何运营一家网络公司
- JSP 、J2EE 、C# 、asp.net 、vb、VB.net、php、 Android,FPGA,MATLAB,QT,程序开发
- DIV+CSS规范命名
- 分享一个基于长连接+长轮询+原生的JS及AJAX实现的多人在线即时交流聊天室
- 关于读取数据库进行数据处理的一些小问题
- jquery效果队列
- 新入此地,请多关照
- 用dblink从源数据库导出expdp文件到目标数据库
- MatConvNet教程----- Win7下编译和配置详解
- cocos2d-x 植入广告(二) 有米横屏、插屏广告和积分墙广告
- PHP文件上传大小限制修改
- HTTP状态码
- FaceBook 扎克伯格还有两个月就当爸爸了 Mark Zuckerberg to take two months paternity leave 翻译 by oralusa.com
- 聚会的目的 동창회의 목적 (2015)
- Map集合中的方法(添加、删除、判断、获取)