• BZOJ3123: [Sdoi2013]森林


    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3123

    主席树+启发式合并。

    首先对于每棵树建主席树,然后合并的时候就把点数小的暴力插进点数大的那棵树里面。

    然后查询的话就在主席树上二分就可以了。

    注意点:在暴力重建的过程中边是确确实实要连的否则会丢失信息。。

    调了很久TAT。。

    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define inf 1000000009
    #define ll long long
    using namespace std;
    struct data{int obj,pre;
    }e[165000];
    int sum[24005000],root[80050],ls[24005000],rs[24005000];
    int head[80050],dep[80050],fa[80050][21],a[80050],b[80050],s[80050];
    int bin[21];
    int n,m,q,ans,tot,cnt,tt,num;
    char ch[2];
    int read(){
        int x=0,f=1; char ch=getchar();
        while (!isdigit(ch)){if (ch=='-') f=-1; ch=getchar();}
        while (isdigit(ch)){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    void insert(int x,int y){
        e[++tot].obj=y; e[tot].pre=head[x]; head[x]=tot;
    }
    void add(int l,int r,int x,int &y,int val){
        y=++cnt;
        sum[y]=sum[x]+1;
        if (l==r) return;
        int mid=(l+r)/2;
        if (val<=mid) rs[y]=rs[x],add(l,mid,ls[x],ls[y],val);
        if (val>mid) ls[y]=ls[x],add(mid+1,r,rs[x],rs[y],val);
    }
    void dfs(int u){
        s[u]=1;
        add(1,num,root[fa[u][0]],root[u],a[u]);
        rep(i,1,20) if (dep[u]>=bin[i]) fa[u][i]=fa[fa[u][i-1]][i-1];    
        for (int j=head[u];j;j=e[j].pre){
            int v=e[j].obj;
            if (v!=fa[u][0]){
                fa[v][0]=u; dep[v]=dep[u]+1;
                dfs(v);
                s[u]+=s[v];
            }
        }
    }
    int lca(int x,int y){
        if (dep[x]<dep[y]) swap(x,y);
        int t=dep[x]-dep[y];
        rep(i,0,20) if (t&bin[i]) x=fa[x][i];
        down(i,20,0) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
        if (x==y) return x;
        return fa[x][0]; 
    }
    void cl(int u,int f){
        clr(fa[u],0); dep[u]=0;
        for (int j=head[u];j;j=e[j].pre){
            int v=e[j].obj;
            if (v!=f) cl(v,u);
        }
    }
    void link(int x,int y){
        cl(y,0);
        dep[y]=dep[x]+1; fa[y][0]=x; insert(x,y); insert(y,x);
        dfs(y);
    }
    void rebuild(int x,int y){
        int sx=x,sy=y;
        int t=dep[x]; rep(i,0,20) if (t&bin[i]) x=fa[x][i];
        t=dep[y]; rep(i,0,20) if (t&bin[i]) y=fa[y][i];
        if (s[x]<s[y]) swap(x,y),swap(sx,sy);
        s[x]+=s[y]; link(sx,sy);    
    }
    int solve(int x,int y,int k){
        int z=lca(x,y),t=fa[z][0],a=root[x],b=root[y],c=root[z],d=root[t];
        int l=1,r=num,now=0;
        while (l<r){
            int mid=(l+r)/2;
            now=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]];
            if (now<k) {
                k-=now; 
                a=rs[a],b=rs[b],c=rs[c],d=rs[d];
                l=mid+1;
            }
            else {
                a=ls[a],b=ls[b],c=ls[c],d=ls[d];
                r=mid;
            }
        }
        return l;
    }
    int Find(int x){
        int l=1,r=num,mid;
        while (l<r){
            mid=(l+r)/2;
            if (b[mid]==x) return mid;
            if (b[mid]<x) l=mid+1;
            else r=mid-1;
        }
        return l;
    }
    int main(){
        tt=read();
        bin[0]=1; rep(i,1,20) bin[i]=bin[i-1]*2; 
        ans=0;
            n=read(); m=read(); q=read(); 
            rep(i,1,n) a[i]=read(),b[i]=a[i];
            sort(b+1,b+1+n); num=unique(b+1,b+1+n)-b-1;
            rep(i,1,n) a[i]=Find(a[i]);
            rep(j,1,m){
                int x=read(),y=read();
                insert(x,y); insert(y,x);
            }
            rep(i,1,n) if (!root[i]) dfs(i);
            rep(i,1,q){
                scanf("%s",ch);
                if (ch[0]=='Q'){
                    int x=read()^ans,y=read()^ans,k=read()^ans;
                    ans=b[solve(x,y,k)];
                    printf("%d
    ",ans);
                }
                else {
                    int x=read()^ans,y=read()^ans;
                    rebuild(x,y);
                }
            }
        return 0;
    }
  • 相关阅读:
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 833 字符串中的查找与替换(暴力模拟)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 832 翻转图像(位运算)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    Java实现 LeetCode 831 隐藏个人信息(暴力)
    how to use automapper in c#, from cf~
  • 原文地址:https://www.cnblogs.com/ctlchild/p/5149169.html
Copyright © 2020-2023  润新知