zoukankan      html  css  js  c++  java
  • 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
    ",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;
    }
    

      

  • 相关阅读:
    李航博士:浅谈我对机器学习的理解
    数据挖掘过程中:数据预处理
    C++:构造函数和析构函数能否为虚函数
    PCA的数学原理
    奇异值分解(SVD) --- 几何意义
    3月机器学习在线班第六课笔记--信息熵与最大熵模型
    ML:交叉验证Cross-Validation
    LaTex的注释
    混合高斯模型
    NE2018届校招内推笔试——数据挖掘
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10106671.html
Copyright © 2011-2022 走看看