【BZOJ3123】森林(主席树,启发式合并)
2017-12-26 22:27
330 查看
题面
神TM题面是图片题解
首先,求树链上第k大,请参看BZOJ2588 Count On a Tree这道题目于是增添了一个动态的合并森林的操作
所以直接启发式合并就可以啦
我第一次交直接T了
加了一堆rg就AC了。。。
神奇的register
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define MAX 81000 #define rg register inline int read() { rg int x=0,t=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } struct Line { int v,next; }e[MAX<<1]; int h[MAX],cnt=1; int p[MAX][20]; inline void Add(int u,int v) { e[cnt]=(Line){v,h[u]}; h[u]=cnt++; } struct Node { int ls,rs; int v; }t[MAX<<9]; int tot,n,T,m; int fa[MAX],dep[MAX],rt[MAX],sum,S[MAX]; int a[MAX]; void Modify(int &now,int ff,int l,int r,int pos) { now=++tot; t[now]=t[ff]; t[now].v++; if(l==r)return; int mid=(l+r)>>1; if(pos<=mid)Modify(t[now].ls,t[ff].ls,l,mid,pos); else Modify(t[now].rs,t[ff].rs,mid+1,r,pos); } void Build(int &now,int l,int r) { now=++tot; if(l==r)return; rg int mid=(l+r)>>1; Build(t[now].ls,l,mid); Build(t[now].rs,mid+1,r); } void dfs(int u,int ff) { fa[u]=p[u][0]=ff;dep[u]=dep[ff]+1; Modify(rt[u],rt[ff],1,sum,a[u]); for(int i=1;i<18;++i)p[u][i]=p[p[u][i-1]][i-1]; for(int i=h[u];i;i=e[i].next) { int v=e[i].v; if(v==ff)continue; dfs(v,u); } } int Query(int A,int B,int C,int D,int l,int r,int k) { if(l==r)return l; rg int tmp=t[t[A].ls].v+t[t[B].ls].v-t[t[C].ls].v-t[t[D].ls].v; rg int mid=(l+r)>>1; if(k<=tmp)return Query(t[A].ls,t[B].ls,t[C].ls,t[D].ls,l,mid,k); else return Query(t[A].rs,t[B].rs,t[C].rs,t[D].rs,mid+1,r,k-tmp); } int f[MAX],size[MAX]; int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);} void merge(int x,int y){x=getf(x);y=getf(y);f[y]=x;size[x]+=size[y];size[y]=0;} inline int LCA(int x,int y) { if(dep[x]<dep[y])swap(x,y); for(int i=17;i>=0;--i) if(dep[p[x][i]]>=dep[y])x=p[x][i]; if(x==y)return x; for(int i=17;i>=0;--i) if(p[x][i]!=p[y][i]) x=p[x][i],y=p[y][i]; return p[x][0]; } int main() { read(); n=read();m=read();T=read(); for(rg int i=1;i<=n;++i)S[++sum]=a[i]=read(),size[i]=1; sort(&S[1],&S[sum+1]); sum=unique(&S[1],&S[sum+1])-S-1; for(rg int i=1;i<=n;++i)a[i]=lower_bound(&S[1],&S[sum+1],a[i])-S; Build(rt[0],1,sum); for(rg int i=1;i<=m;++i) { rg int x=read(),y=read(); Add(x,y);Add(y,x); if(size[getf(x)]>size[getf(y)])merge(x,y); else merge(y,x); } for(rg int i=1;i<=n;++i) { if(!rt[i]) dfs(i,0); } rg char ch[20]; rg int ls=0; while(T--) { scanf("%s",ch); if(ch[0]=='Q') { rg int u=read()^ls,v=read()^ls,k=read()^ls; rg int lca=LCA(u,v); printf("%d\n",ls=S[Query(rt[u],rt[v],rt[lca],rt[p[lca][0]],1,sum,k)]); } else { rg int x=read()^ls,y=read()^ls; if(size[getf(x)]>size[getf(y)])swap(x,y); merge(y,x); dfs(x,y); Add(x,y);Add(y,x); } } return 0; }
相关文章推荐
- [bzoj3123][Sdoi2013]森林_主席树_启发式合并
- 【BZOJ3123】森林(主席树,启发式合并)
- 【BZOJ-3123】森林 主席树 + 启发式合并
- 【BZOJ3123】[Sdoi2013]森林 主席树+倍增LCA+启发式合并
- bzoj 3123 [Sdoi2013]森林(主席树,lca,启发式合并)
- [bzoj3123][洛谷P3302] [SDOI2013]森林(树上主席树+倍增lca+启发式合并)
- BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]
- BZOJ_3123_[Sdoi2013]森林_主席树+启发式合并
- 【bzoj3123】【sdoi2013】【森林】【启发式合并+主席树】
- BZOJ 3123 森林 主席树启发式合并
- BZOJ 3123: [Sdoi2013]森林|主席树|启发式合并
- [主席树 启发式合并] BZOJ 3123 [Sdoi2013]森林
- 【BZOJ 3123】 [Sdoi2013]森林 主席树启发式合并
- [BZOJ3123][Sdoi2013]森林(主席树+启发式合并)
- [BZOJ3123][Sdoi2013]森林(主席树启发式合并)
- [BZOJ3123][Sdoi2013]森林(主席树+启发式合并)
- BZOJ 3123: [Sdoi2013]森林 启发式合并 树上主席树
- [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)
- Bzoj 3123: [Sdoi2013]森林(主席树+启发式合并)
- BZOJ 3123 主席树 启发式合并