P3302 [SDOI2013]森林

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;
}

 

  

 

posted @ 2018-12-12 09:42  y2823774827y  阅读(220)  评论(0编辑  收藏  举报