• #主席树,dsu on tree,树上倍增#洛谷 3302 [SDOI2013]森林


    题目


    分析

    (k)大的问题可以用主席树解决,
    下标为节点离散化后的权值,
    连边操作考虑合并两棵树,
    如果暴力合并那肯定会T飞,考虑启发式合并
    同时维护子树内的lca,方便主席树的查询


    代码

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define rr register
    using namespace std;
    const int N=80011; struct node{int y,next;}e[N<<1];
    int a[N],b[N],n,m,k=1,Q,fat[N],f[N][17],siz[N],dep[N],rt[N],ls[N],M;
    struct Chair{
        int w[N<<7],ls[N<<7],rs[N<<7],cnt;
        inline void build(int &rt,int l,int r){
            w[rt=++cnt]=0; rr int mid=(l+r)>>1;
            if (l<r) build(ls[rt],l,mid),build(rs[rt],mid+1,r); 
        }
        inline void update(int &rt,int l,int r,int k){
            rr int trt=++cnt,mid=(l+r)>>1;
            ls[trt]=ls[rt],rs[trt]=rs[rt],w[trt]=w[rt]+1,rt=trt;
            if (l==r) return;
            k<=mid?update(ls[trt],l,mid,k):update(rs[trt],mid+1,r,k);
        }
        inline signed query(int fi,int se,int th,int fo,int l,int r,int kth){
        	if (l==r) return b[l];
        	rr int mid=(l+r)>>1,lef=w[ls[fi]]+w[ls[se]]-w[ls[th]]-w[ls[fo]];
        	if (kth<=lef) return query(ls[fi],ls[se],ls[th],ls[fo],l,mid,kth);
        	    else query(rs[fi],rs[se],rs[th],rs[fo],mid+1,r,kth-lef);
        	
    	}
    }Tre;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline void print(int ans){
    	if (ans>9) print(ans/10);
    	putchar(ans%10+48);
    }
    inline signed getf(int u){return fat[u]==u?u:fat[u]=getf(fat[u]);}
    inline void add(int x,int y){
    	e[++k]=(node){y,ls[x]},ls[x]=k;
    	e[++k]=(node){x,ls[y]},ls[y]=k;
    }
    inline void dfs(int x,int fa,int root){
    	f[x][0]=fa,dep[x]=dep[fa]+1,fat[x]=fa,++siz[root];
    	for (rr int i=1;i<=16;++i) f[x][i]=f[f[x][i-1]][i-1];
    	Tre.update(rt[x]=rt[fa],1,M,a[x]);
    	for (rr int i=ls[x];i;i=e[i].next)
    	if (e[i].y!=fa) dfs(e[i].y,x,root);
    }
    inline signed lca(int x,int y){
    	if (dep[x]<dep[y]) x^=y,y^=x,x^=y;
    	for (rr int i=16;~i;--i)
    	if (dep[f[x][i]]>=dep[y]) x=f[x][i];
        if (x==y) return x;
        for (rr int i=16;~i;--i)
        if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    signed main(){
    	iut(),n=iut(),m=iut(),Q=iut(),Tre.cnt=0;
    	for (rr int i=1;i<=n;++i) b[i]=a[i]=iut(),fat[i]=i;
    	for (rr int i=1;i<=m;++i) add(iut(),iut());
    	sort(b+1,b+1+n),M=unique(b+1,b+1+n)-b-1,Tre.build(rt[0],1,M);
    	for (rr int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+1+M,a[i])-b;
    	for (rr int i=1;i<=n;++i) if (fat[i]==i) dfs(i,0,i),fat[i]=i;
    	for (rr int lans=0;Q;--Q){
    		rr char c=getchar();
    		while (c!='Q'&&c!='L') c=getchar();
            rr int x=iut()^lans,y=iut()^lans;
            if (c=='L'){
            	rr int fa=getf(x),fb=getf(y); add(x,y);
            	if (siz[fa]<siz[fb])
    			    fa^=fb,fb^=fa,fa^=fb,
    			        x^=y,y^=x,x^=y;
    			dfs(y,x,fa);
    		}else{
    			rr int kth=iut()^lans,LCA=lca(x,y);
    			lans=Tre.query(rt[x],rt[y],rt[LCA],rt[f[LCA][0]],1,M,kth);
    			print(lans),putchar(10);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    The Instruments Workflow
    About Instruments
    视频播放插件Video.js
    各大三方API
    Xib、AutoLayout等使用心得
    克隆示例
    接口类型的多重继承
    高级着色语言简介
    DirectX Box
    Direct3D初始化
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13820873.html
Copyright © 2020-2023  润新知