• [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
    ",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
    ",last=query(x,y,K-1));
    		}
    		if(ch=='L')
    			link(x,y);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    正则表达式和re模块
    面向对象基础
    面向对象高级
    网络编程
    collectiontimeossysjson模块
    继承
    封装
    我在吃饭
    111
    关于羽毛球拍
  • 原文地址:https://www.cnblogs.com/chadinblog/p/6525655.html
Copyright © 2020-2023  润新知