• BZOJ 3123 主席树 启发式合并


    思路:
    主席树 搞树上的k大 x+y-lca(x,y)-fa(lca(x,y))
    按照size小树往大树上插 启发式合并
    n*log^2n的 搞定~

    //By SiriusRen
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 666666
    const int inf=1000000000;char op[2];
    int cases,n,m,t,a[N],first[N],next[N],v[N],w[N],tot,ans;
    int xx,yy,zz,jy,f[N],wei[N],size[N],fa[N][22],deep[N],root[N],cnt;
    int tree[N*50],lson[N*50],rson[N*50];
    int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
    void merge(int x,int y){int fx=find(x),fy=find(y);f[fx]=fy,size[fy]+=size[fx];}
    void add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
    void insert(int x,int &y,int l,int r,int val){
        if(!y)y=++cnt;
        tree[y]=tree[x]+1;
        if(l==r)return;
        int mid=(l+r)>>1;
        if(val<=mid)rson[y]=rson[x],insert(lson[x],lson[y],l,mid,val);
        else lson[y]=lson[x],insert(rson[x],rson[y],mid+1,r,val);
    }
    void dfs(int x){
        for(int i=1;i<=19;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
        deep[x]=deep[fa[x][0]]+1,root[x]=0;
        insert(root[fa[x][0]],root[x],0,inf,wei[x]);
        for(int i=first[x];~i;i=next[i])if(v[i]!=fa[x][0])
            fa[v[i]][0]=x,dfs(v[i]);
    }
    int lca(int x,int y){
        if(deep[x]<deep[y])swap(x,y);
        for(int i=19;~i;i--)if(deep[fa[x][i]]>=deep[y])x=fa[x][i];
        if(x==y)return x;
        for(int i=19;~i;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
        return fa[x][0];
    }
    int kth(int x,int y,int lca,int falca,int l,int r,int k){
        if(l==r)return l;
        int mid=(l+r)>>1;
        int temp=tree[lson[x]]+tree[lson[y]]-tree[lson[lca]]-tree[lson[falca]];
        if(k<=temp)return kth(lson[x],lson[y],lson[lca],lson[falca],l,mid,k);
        else return kth(rson[x],rson[y],rson[lca],rson[falca],mid+1,r,k-temp);
    }
    int main(){
        scanf("%d",&cases);
        memset(first,-1,sizeof(first)),tot=ans=cnt=0;
        scanf("%d%d%d",&n,&m,&t);
        for(int i=1;i<=n;i++)scanf("%d",&wei[i]),f[i]=i,size[i]=1;
        for(int i=1;i<=m;i++)
            scanf("%d%d",&xx,&yy),
            add(xx,yy),add(yy,xx),merge(xx,yy);
        for(int i=1;i<=n;i++)if(!fa[i][0])dfs(i);
        for(int i=1;i<=t;i++){
            scanf("%s%d%d",op,&xx,&yy),xx^=ans,yy^=ans;
            if(op[0]=='Q')
                scanf("%d",&zz),zz^=ans,jy=lca(xx,yy),
                printf("%d
    ",ans=kth(root[xx],root[yy],root[jy],root[fa[jy][0]],0,inf,zz));
            else{
                int fx=find(xx),fy=find(yy);
                if(size[fx]>size[fy])swap(xx,yy);
                add(xx,yy),add(yy,xx),merge(xx,yy),fa[xx][0]=yy,dfs(xx);
            }
        }
    }

    这里写图片描述

  • 相关阅读:
    sublime text 4 vim 插件配置
    ssh-keygen 的使用
    distribution transaction solution
    bilibili 大数据 视频下载 you-get
    Deepin 20.2.1 安装 MS SQL 2019 容器版本
    【转】使用Linux下Docker部署MSSQL并加载主机目录下的数据库
    【转】You Can Now Use OneDrive in Linux Natively Thanks to Insync
    dotnet 诊断工具安装命令
    Linux 使用 xrandr 设置屏幕分辨率
    【转】CentOS 7.9 2009 ISO 官方原版镜像下载
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532099.html
Copyright © 2020-2023  润新知