SDOI2013 森林
题目链接:戳我
呜呜呜又被dreagonm嘲讽了,但是我真的不会写数据结构啊QAQ
链上求第K大+启发式合并
(以下是重构第三遍的代码QAQ)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 100010
using namespace std;
int n,m,lastans,tt,sum,tot,T,q;
int f[MAXN],siz[MAXN],p[MAXN][19];
int fa[MAXN],dep[MAXN],rt[MAXN],S[MAXN],a[MAXN],head[MAXN];
struct Edge{int nxt,to;}edge[MAXN<<1];
struct Node{int ls,rs,v;}t[MAXN<<9];
inline void add(int from,int to){edge[++tt].nxt=head[from],edge[tt].to=to,head[from]=tt;}
inline void update(int &x,int f,int l,int r,int pos)
{
x=++tot;
t[x]=t[f],t[x].v++;
if(l==r) return;
int mid=(l+r)>>1;
if(pos<=mid) update(t[x].ls,t[f].ls,l,mid,pos);
else update(t[x].rs,t[f].rs,mid+1,r,pos);
}
inline int query(int x,int y,int lca1,int lca2,int l,int r,int k)
{
if(l==r) return l;
int cur=t[t[x].ls].v+t[t[y].ls].v-t[t[lca1].ls].v-t[t[lca2].ls].v;
int mid=(l+r)>>1;
if(k<=cur) return query(t[x].ls,t[y].ls,t[lca1].ls,t[lca2].ls,l,mid,k);
else return query(t[x].rs,t[y].rs,t[lca1].rs,t[lca2].rs,mid+1,r,k-cur);
}
inline int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
inline void merge(int x,int y)
{
int xx=find(x),yy=find(y);
f[xx]=yy;
siz[yy]+=siz[xx],siz[xx]=0;
}
inline int get_lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
int cur=dep[x]-dep[y];
for(int i=17;i>=0;i--)
if(cur&(1<<i))
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 fa[x];
}
inline void dfs(int x,int pre)
{
fa[x]=p[x][0]=pre;
dep[x]=dep[pre]+1;
update(rt[x],rt[pre],1,sum,a[x]);
for(int i=1;i<=17;i++)
p[x][i]=p[p[x][i-1]][i-1];
for(int i=head[x];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==pre) continue;
dfs(v,x);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d",&T);
memset(head,0,sizeof(head));
tt=0;
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),siz[i]=1;
memcpy(S,a,sizeof(a));
sort(&S[1],&S[n+1]);
sum=unique(&S[1],&S[n+1])-S-1;
for(int i=1;i<=n;i++) a[i]=lower_bound(&S[1],&S[sum+1],a[i])-S;
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
if(siz[find(x)]>siz[find(y)]) merge(y,x);
else merge(x,y);
}
for(int i=1;i<=n;i++)
{
if(!rt[i])
dfs(i,0);
}
lastans=0;
for(int i=1;i<=q;i++)
{
char s[10];
int x,y,k;
scanf("%s",s);
if(s[0]=='Q')
{
scanf("%d%d%d",&x,&y,&k);
x^=lastans,y^=lastans,k^=lastans;
int lca=get_lca(x,y);
printf("%d\n",lastans=S[query(rt[x],rt[y],rt[lca],rt[fa[lca]],1,sum,k)]);
}
else
{
scanf("%d%d",&x,&y);
x^=lastans,y^=lastans;
if(siz[find(x)]>siz[find(y)]) swap(x,y);
merge(x,y);
dfs(x,y);
add(x,y),add(y,x);
}
}
return 0;
}