[SDOI2013]森林 主席树 启发式合并

 

Code:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<string>
#include<cstring>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define CLR(x,c) memset(x,c,sizeof x)
int read(){ int a; scanf("%d",&a); return a;}

using namespace std;

void SetIO(string a){
	string in = a + ".in";
	freopen(in.c_str(), "r" ,stdin);
}

const int maxn=80000+5;

int n, m, T;

int val[maxn], Sorted[maxn];

void Discrete(){
	sort(Sorted + 1, Sorted + 1 + n);
	for(int i = 1;i <= n; ++i){
		val[i] = lower_bound(Sorted + 1, Sorted + 1 + n, val[i]) - Sorted;
	}
}

int head[maxn], nex[maxn<<1], to[maxn<<1], edges;

void add_edge(int u, int v){
	nex[++edges] = head[u];
	head[u] = edges;
	to[edges] = v;
}

void Read(){
	n=read(),n=read(),m=read(), T=read();
	REP(i,1,n) val[i]=read(), Sorted[i] = val[i];

	REP(i,1,m){
		int a=read(),b=read();
		add_edge(a,b);
		add_edge(b,a);
	}
}

const int const_Tree=300;

int root[maxn],numv[maxn*const_Tree];

struct Chair_Tree{
	int cnt_Tree, lson[maxn*const_Tree], rson[maxn * const_Tree];

	void build(int l,int r,int &o){
		if(l > r)return;
		o = ++cnt_Tree;
		int mid=(l + r) >> 1;
		build(l, mid, lson[o]);
		build(mid + 1, r, rson[o]);
	}

	int insert(int l, int r, int o, int pos){
		int oo=++cnt_Tree;
		lson[oo] = lson[o];
		rson[oo] = rson[o];
		numv[oo] = numv[o] + 1;

		if(l == r) return oo;

		int mid=(l+r)>>1;	
		if(pos <= mid) lson[oo] = insert(l,mid,lson[o],pos);
		else rson[oo] = insert(mid+1,r,rson[o],pos);
		return oo;
	}

	int query(int l,int r,int u,int v,int lca,int flca,int k){
		if(l==r)return l;

		int lsum=numv[lson[u]]+numv[lson[v]]-numv[lson[lca]]-numv[lson[flca]];
		int mid=(l+r)>>1;

		if(k<=lsum) 
			return query(l,mid,lson[u],lson[v],lson[lca],lson[flca],k);
		else 
			return query(mid+1,r,rson[u],rson[v],rson[lca],rson[flca],k-lsum);
	}

}Tree;

const int log_Tree = 17;

int dep[maxn], f[log_Tree + 3][maxn],siz[maxn];

int dfs(int u,int fa,int depth){
	f[0][u]=fa;
	siz[u]=1;
	dep[u]=depth;
	REP(i,1,log_Tree)
		f[i][u] = f[i-1][f[i-1][u]];	

	root[u]=Tree.insert(1,n,root[fa],val[u]);

	for(int v = head[u];v;v = nex[v]){
		if(to[v]==fa) continue;
		siz[u]+=dfs(to[v],u,depth+1);
	}
	return siz[u];
}

void Build(){
	REP(i,1,n)
		if(!dep[i]) dfs(i, 0, 1);
}

int get_lca(int a,int b){
	if(dep[a] > dep[b]) swap(a,b);

	if(dep[a] != dep[b]){
		for(int i=log_Tree;i>=0;--i){
			if(dep[f[i][b]]>=dep[a]) b=f[i][b];
		}
	}

	if(a==b)return a;


	for(int i=log_Tree;i>=0;--i){
		if(f[i][a]!=f[i][b]){
			a=f[i][a];
			b=f[i][b];
		}
	}

	return f[0][a];
}

void Work(){
	int lastans=0;
	REP(i,1,T)
	{
		char opt[3];
		scanf("%s",opt);
		int u,v,k;
		u=read(),v=read();

		u^=lastans, v ^= lastans;

		if(opt[0] == 'Q'){
			k=read();
			k^=lastans;
			int lca=get_lca(u,v);
			int flca=f[0][lca];

			lastans=Tree.query(1,n,root[u],root[v],root[lca],root[flca],k);
			lastans=Sorted[lastans];
			printf("%d\n",lastans);
		}

		if(opt[0] == 'L'){
			add_edge(u,v);
			add_edge(v,u);
			if(siz[u]>siz[v]){
				siz[u]+=dfs(v,u,dep[u]+1);
			}
			else{
				siz[v]+=dfs(u,v,dep[v]+1);
			}
		}
	} 
}

void Init(){
	Read();
	Discrete();
	Build();
}

int main(){
	SetIO("input");
	Init();
	Work();
	return 0;
}

  

posted @ 2018-10-20 15:55  EM-LGH  阅读(144)  评论(0编辑  收藏  举报