BZOJ2733 [HNOI2012]永无乡 平衡树启发式合并
来源:互联网 发布:数据自动统计分析方法 编辑:程序博客网 时间:2024/06/05 06:59
首先因为题目中涉及到查询第K小值,所以用平衡树来维护每个连通分支的信息。
那么加边这个操作怎么实现呢?其实就是将任意的两个平衡树合并。给我们的直观感受是把小的树合并到大的树里比较高效。
事实上,这样做的话,所有合并操作可以在O(nlog^2n)之内解决。
为什么呢?可以这样来分析。每个节点经过一次合并操作以后,它所在的树的大小至少要加倍,那么也就是说至多一个节点被合并操作影响logn次,每次合并后的插入操作要O(logn)时间,共有n个节点,就得到了O(nlog^2n)的时间复杂度。
吐槽一下数据……刚开始我没判断加边操作的两边是否已经在同一个连通分支内,就直接把树复制了一遍……竟然也AC了。下面的代码是改正以后的代码。
//BZOJ2733#include<iostream>#include<cstdio>#include<algorithm>#include<string>#include<cstring>#include<vector>#include<queue>#include<ctime>#include<cstdlib>using namespace std;const int MAXN=100010;struct Treap_Node{int ch[2],key,dat,size,sub;}Treap[MAXN<<5];int p[MAXN],sz[MAXN],root[MAXN],ip[MAXN],n,m,in1,in2,q,tot;char op[10];int find(int x){if(p[x]==x) return x;p[x]=find(p[x]);return p[x];}inline void uni(int i,int j){sz[find(j)]+=sz[find(i)];p[find(i)]=find(j);}inline int cmp(int x,int tar){return (Treap[x].dat>tar)?0:1;}inline void maintain(int x){Treap[x].size=Treap[Treap[x].ch[0]].size+1+Treap[Treap[x].ch[1]].size;}inline void rotate(int &x,int d){int p=Treap[x].ch[d^1];Treap[x].ch[d^1]=Treap[p].ch[d];Treap[p].ch[d]=x;maintain(x);maintain(p);x=p;}void ins(int &x,int tar,int s){if(!x){Treap[++tot].dat=tar,Treap[tot].sub=s,Treap[tot].key=rand();Treap[tot].size=1,x=tot;return;}int d=cmp(x,tar);ins(Treap[x].ch[d],tar,s);if(Treap[Treap[x].ch[d]].key>Treap[x].key) rotate(x,d^1);maintain(x);}int getKth(int x,int k){if(k<=Treap[Treap[x].ch[0]].size) return getKth(Treap[x].ch[0],k);k-=Treap[Treap[x].ch[0]].size+1;if(k<=0) return Treap[x].sub;else return getKth(Treap[x].ch[1],k);}void mergeto(int x,int &y){ins(y,Treap[x].dat,Treap[x].sub);if(Treap[x].ch[0]) mergeto(Treap[x].ch[0],y);if(Treap[x].ch[1]) mergeto(Treap[x].ch[1],y);}int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) scanf("%d",&ip[i]);for(int i=1;i<=n;i++) p[i]=i,sz[i]=1;for(int i=1;i<=m;i++){scanf("%d%d",&in1,&in2);if(find(in1)!=find(in2)) uni(in1,in2);}for(int i=1;i<=n;i++) ins(root[find(i)],ip[i],i);scanf("%d",&q);for(int i=1;i<=q;i++){scanf("%s%d%d",op,&in1,&in2);if(op[0]=='B'&&find(in1)!=find(in2)){int s1=sz[find(in1)],s2=sz[find(in2)];if(s1>s2){mergeto(root[find(in2)],root[find(in1)]);uni(in2,in1);}else{mergeto(root[find(in1)],root[find(in2)]);uni(in1,in2);}}else if(op[0]=='Q'){if(sz[find(in1)]<in2) puts("-1");else printf("%d\n",getKth(root[find(in1)],in2));}}return 0;}
0 0
- BZOJ2733 [HNOI2012]永无乡 平衡树启发式合并
- [BZOJ2733]HNOI2012永无乡|平衡树启发式合并
- [BZOJ2733][HNOI2012][启发式合并][平衡树]永无乡
- [平衡树+启发式合并] BZOJ2733: [HNOI2012]永无乡
- [BZOJ2733][HNOI2012]永无乡(平衡树+启发式合并)
- bzoj2733: [HNOI2012]永无乡 splay+启发式合并
- 【bzoj2733】【HNOI2012】【永无乡】【treap+启发式合并】
- 【BZOJ2733】[HNOI2012]永无乡【启发式合并】【Splay】
- BZOJ2733: [HNOI2012]永无乡 Splay启发式合并
- [BZOJ2733][HNOI2012]永无乡-Treap-启发式合并
- bzoj2733 [HNOI2012]永无乡(splay启发式合并)
- [BZOJ2733][HNOI2012]永无乡(并查集+splay启发式合并)
- BZOJ 2733 2733: [HNOI2012]永无乡 平衡树启发式合并
- BZOJ2733 永无乡 [启发式合并]
- BZOJ2733 永无乡 【splay启发式合并】
- [BZOJ2733][HNOI2012永无乡][线段树合并+并查集]
- [bzoj2733][HNOI2012]永无乡 线段树合并+并查集
- [HNOI2012]永无乡 SBT+启发式合并
- [Matlab][数据挖掘算法][感知机]
- 任务调度与伪共享问题
- 浅析pthread_cond_wait
- LINUX(创建、删除文件和文件夹命令)
- 06.黑马程序员-点语法、成员变量作用域
- BZOJ2733 [HNOI2012]永无乡 平衡树启发式合并
- win7 visual studio 2010 安装错误
- 每天一点iOS知识回顾1
- java Swing编程之布局管理器简单实例DEMO
- 九度 Prime Ring Problem hdu 1016
- 思科寄存器值
- 对象模型图【OMD】阅读指南
- 学习记录
- Java Doc 建议不要使用 JPasswordField.getText()