[bzoj 3123][Sdoi2013]森林

这题的技术性不高.

查询的时候按照树上链查询第K大做法做.

连边的时候可以启发式合并,暴力的将一个合并到另一个.

由于是树上的主席树,所以这两个操作维护起来并不是特别困难.

平心而论,对于这道题,出题人是给了我们很多方便的.

还有一个地方是,刚开始输入的T是在比赛时区分数据点数的,没什么用,别看成多组数据.

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<ctime>
#include<string>
#include<iomanip>
#include<algorithm>
#include<map>
using namespace std;
#define LL long long
#define FILE "rforest"
#define up(i,j,n) for(int i=j;i<=n;++i)
#define db double
#define ull unsigned long long
#define eps 1e-10
#define pii pair<int,int>
int read(){
	int x=0,f=1,ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return f*x;
}
const int maxn=202000,maxm=20000,mod=(int)(1e9+7+0.1),inf=(int)(1e9);
bool cmax(int& a,int b){return a<b?a=b,true:false;}
bool cmin(int& a,int b){return a>b?a=b,true:false;}
struct node{
	int y,next;
}e[maxn];
int len=0,linkk[maxn];
void insert(int x,int y){e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;}
int fa[maxn][27],dep[maxn],siz[maxn],f[maxn],vis[maxn];
int val[maxn],N,zhu[maxn],v[maxn];
int getfa(int x){return x==f[x]?x:f[x]=getfa(f[x]);}
pii t[maxn];
namespace chair_man_tree{
	const int maxn=10000000;
	int c[maxn][2],sum[maxn],cnt=0,root[maxn];
	void insert(int pre,int& o,int key,int l,int r){
		o=++cnt;
		if(l==r){
			sum[o]=sum[pre]+1;
			return;
		}
		int mid=(l+r)>>1;
		if(key>mid){
			c[o][0]=c[pre][0];
			insert(c[pre][1],c[o][1],key,mid+1,r);
		}
		else{
			c[o][1]=c[pre][1];
			insert(c[pre][0],c[o][0],key,l,mid);
		}
		sum[o]=sum[c[o][0]]+sum[c[o][1]];
	}
	void build(int x){
		insert(root[fa[x][0]],root[x],zhu[x],1,N);
	}
	int q[5],w[5];
	int query(int K,int l,int r){
		int ans=0;up(i,1,4)ans+=w[i]*sum[c[q[i]][0]];
		int mid=(l+r)>>1;
		if(l==r)return r;
		if(ans<=K){
			up(i,1,4)q[i]=c[q[i]][1];K-=ans;
			return query(K,mid+1,r);
		}
		else {
			up(i,1,4)q[i]=c[q[i]][0];
			return query(K,l,mid);
		}
	}
	int Query(int K){
		return query(K,1,N);
	}
};
void dfs(int x){
	vis[x]=1;
	chair_man_tree::build(x);
	for(int i=linkk[x];i;i=e[i].next){
		if(e[i].y==fa[x][0])continue;
		fa[e[i].y][0]=x;
		f[e[i].y]=x;
		dep[e[i].y]=dep[x]+1;
		dfs(e[i].y);
	}
	getfa(x);
}
int getlca(int x,int y){
	if(dep[x]>dep[y])swap(x,y);
	for(int i=25;i>=0;i--)if(dep[y]-dep[x]>=(1<<i))y=fa[y][i];
	if(x==y)return x;
	for(int i=25;i>=0;i--)if(fa[y][i]!=fa[x][i])x=fa[x][i],y=fa[y][i];
	return fa[x][0];
}
int query(int S,int T,int K){
	int lca=getlca(S,T);
	up(i,1,4)chair_man_tree::w[i]=(i>2?-1:1);
	chair_man_tree::q[1]=chair_man_tree::root[S];
	chair_man_tree::q[2]=chair_man_tree::root[T];
	chair_man_tree::q[3]=chair_man_tree::root[lca];
	chair_man_tree::q[4]=chair_man_tree::root[fa[lca][0]];
	return val[chair_man_tree::Query(K)];
}
int q[maxn],tail=0;
void Dfs(int x){
	chair_man_tree::build(x);
	q[++tail]=x;
	for(int i=linkk[x];i;i=e[i].next){
		if(e[i].y==fa[x][0])continue;
		dep[e[i].y]=dep[x]+1;
		fa[e[i].y][0]=x;
		f[e[i].y]=fa[e[i].y][0];
		Dfs(e[i].y);
	}
	getfa(x);
}
void link(int x,int y){
	int f1=getfa(x),f2=getfa(y);
	if(siz[f1]<siz[f2])swap(x,y),swap(f1,f2);
	dep[y]=dep[x]+1;
	insert(x,y);insert(y,x);
	fa[y][0]=x;f[y]=f1;
	tail=0;
	Dfs(y);
	for(int j=1;j<=25;j++)
		for(int i=1;i<=tail;i++)
			fa[q[i]][j]=fa[fa[q[i]][j-1]][j-1];
	up(i,1,tail)siz[getfa(q[i])]++;
}
void print(int* a,int n){
	up(i,0,n)if(a[i])printf("%d %d\n",i,a[i]);
	//cout<<endl;
}
int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	int T=read();
	int n=read(),m=read(),Q=read();
	up(i,1,n)t[i].first=v[i]=read(),t[i].second=i;
	sort(t+1,t+n+1);t[0].first=-1;
	up(i,1,n){
		if(t[i].first!=t[i-1].first){
			val[++N]=t[i].first;
		}
		zhu[t[i].second]=N;
	}//hash
	up(i,1,m){
		int x=read(),y=read();
		insert(x,y);insert(y,x);
	}
	up(i,1,n)if(!vis[i])f[i]=i,dfs(i);
	up(i,1,n)siz[getfa(i)]++;
	for(int j=1;j<=25;j++)
		for(int i=1;i<=n;i++)
			fa[i][j]=fa[fa[i][j-1]][j-1];
	int last=0;char ch;
	while(Q--){
		scanf(" %c",&ch);
		int x=read()^last,y=read()^last;
		if(ch=='Q'){
			int K=read()^last;
			printf("%d\n",last=query(x,y,K-1));
		}
		if(ch=='L')
			link(x,y);
	}
	return 0;
}

  

posted @ 2017-03-09 14:50  CHADLZX  阅读(166)  评论(0编辑  收藏  举报