P3302 [SDOI2013]森林
题目大意
n个节点的带权树,初始m条边,q个操作,支持查询x到y间k小值,连边两个操作 n,m,q<=8*10^4
$Kth$自然想到主席树,小子树接到大子树后暴力合并就好了
$Dfs$时顺便以父节点为前驱继承节点建树
Ps:输入里的testcase只是测试点编号,不是该测试点的多组数据
My complete code:
#include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<iostream> using namespace std; typedef long long LL; const LL maxn=200000; inline LL read(){ LL x=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9'){ x=x*10+c-'0'; c=getchar(); }return x*f; } struct node{ LL to,next; }dis[maxn]; LL T,n,m,q,num,nod,cnt; LL head[maxn],val[maxn],b[maxn],father[maxn],inc[maxn][25]; LL dep[maxn],date[maxn<<7],lt[maxn<<7],rt[maxn<<7],root[maxn],size[maxn]; bool visit[maxn]; inline void Add(LL u,LL v){ dis[++num]=(node){v,head[u]}; head[u]=num; } inline LL Two_part(LL x){ return (lower_bound(b+1,b+1+cnt,val[x])-b); } LL Find(LL x){ return father[x]=father[x]==x?x:Find(father[x]); } void Update(LL &now,LL pre,LL l,LL r,LL c){ now=++nod; date[now]=date[pre]+1; LL mid=(l+r)>>1; if(l==r) return; if(c<=mid){ Update(lt[now],lt[pre],l,mid,c); rt[now]=rt[pre]; }else{ Update(rt[now],rt[pre],mid+1,r,c); lt[now]=lt[pre]; } } void Dfs(LL u,LL fa,LL R){ dep[u]=dep[fa]+1; inc[u][0]=fa; for(LL i=1;i<=20;++i) inc[u][i]=inc[inc[u][i-1]][i-1]; size[R]++; father[u]=fa; Update(root[u],root[fa],1,cnt,Two_part(u)); for(LL i=head[u];i;i=dis[i].next){ LL v=dis[i].to; if(v==fa) continue; Dfs(v,u,R); } visit[u]=true; } inline LL LCA(LL x,LL y){ if(dep[x]<dep[y]) swap(x,y); for(LL i=20;i>=0;--i) if(dep[inc[x][i]]>=dep[y]) x=inc[x][i]; if(x==y) return x; for(LL i=20;i>=0;--i) if(inc[x][i]!=inc[y][i]) x=inc[x][i], y=inc[y][i]; return inc[x][0]; } LL query(LL x,LL y,LL lca,LL fa,LL l,LL r,LL c){ LL sum=date[lt[x]]+date[lt[y]]-date[lt[fa]]-date[lt[lca]]; LL mid=(l+r)>>1; if(l==r) return b[l]; if(c<=sum) return query(lt[x],lt[y],lt[lca],lt[fa],l,mid,c); else return query(rt[x],rt[y],rt[lca],rt[fa],mid+1,r,c-sum); } int main(){ T=read(); T=1; while(T--){ n=read(); m=read(); q=read(); for(LL i=1;i<=n;++i){ val[i]=read(); b[i]=val[i]; } sort(b+1,b+1+n); cnt=unique(b+1,b+1+n)-b-1; for(LL i=1;i<=m;++i){ LL u=read(),v=read(); Add(u,v); Add(v,u); } for(LL i=1;i<=n;++i) if(!visit[i]){ Dfs(i,0,i); father[i]=i; } LL last_ans=0; for(LL i=1;i<=q;++i){ char c; LL x,y,k; scanf(" %c",&c); if(c=='Q'){ x=read()^last_ans; y=read()^last_ans; k=read()^last_ans; LL lca=LCA(x,y); LL fa=inc[lca][0]; printf("%lld\n",last_ans=query(root[x],root[y],root[lca],root[fa],1,cnt,k)); }else{ x=read()^last_ans; y=read()^last_ans; Add(x,y); Add(y,x); LL fx=Find(x),fy=Find(y); if(size[fx]>size[fy]){ swap(fx,fy); swap(x,y); } Dfs(x,y,fy); } } } return 0; }