【CodeVS 1477】 永无乡 |Splay

来源:互联网 发布:搜索引擎源码 编辑:程序博客网 时间:2024/06/14 23:41

Splay的启发式合并 每次把小的树拆开放在插入在大树里

这样可以保证复杂度

#include <cstdio>#include <iostream>#include <algorithm> using namespace std;#define MAXN 100010int father[MAXN],root[MAXN];int fa[MAXN],to[MAXN][2],size[MAXN],num[MAXN],id[MAXN];int n,m;int laji[MAXN],top;void Up(int x){ size[x]=size[to[x][0]]+size[to[x][1]]+1; }void Rotate(int &rt,int x){int y=fa[x],z=fa[y];if(y==rt) rt=x;else to[z][to[z][1]==y]=x;int c=to[y][1]==x;fa[x]=z;fa[y]=x;fa[to[x][c^1]]=y;to[y][c]=to[x][c^1];to[x][c^1]=y;Up(y);Up(x); }void Splay(int &rt,int x){while(rt!=x){if(fa[x]!=rt) Rotate(rt,fa[x]);Rotate(rt,x);}}void Ins(int &now,int &rt,int ID,int NUM,int last){if(now==0){now=laji[top--];num[now]=NUM;id[now]=ID;fa[now]=last;size[now]=1;Splay(rt,now);return ;}if(NUM<=num[now]) Ins(to[now][0],rt,ID,NUM,now);else Ins(to[now][1],rt,ID,NUM,now);}void Dfs(int &rt,int now){if(now==0) return ;Dfs(rt,to[now][0]);Dfs(rt,to[now][1]);Ins(rt,rt,id[now],num[now],0);fa[now]=to[now][0]=to[now][1]=size[now]=id[now]=num[now]=0;laji[++top]=now;}int F(int x){if(father[x]!=x) father[x]=F(father[x]);return father[x];}void Link(int x,int y){x=F(x);y=F(y);if(x==y) return ;int sx=size[root[x]];int sy=size[root[y]];if(sx<sy) swap(x,y);Dfs(root[x],root[y]);father[y]=x;}int Q(int now,int k){if(now==0) return -1;int tmp=size[now]-size[to[now][1]];if(tmp==k) return id[now];else if(tmp<k) return Q(to[now][1],k-tmp);else return Q(to[now][0],k);}int main(){cin >>n >>m;int x,y,q;char s[20];for(int i=1;i<MAXN;i++) laji[++top]=i;for(int i=1;i<MAXN;i++) father[i]=i; for(int i=1;i<=n;i++) scanf("%d",&x),Ins(root[i],root[i],i,x,0);for(int i=1;i<=m;i++) scanf("%d %d",&x,&y),Link(x,y);cin >>q;while(q--){scanf("%s %d %d",s+1,&x,&y);if(s[1]=='Q') printf("%d\n",Q(root[F(x)],y));else Link(x,y);}return 0;}


0 0