zoukankan      html  css  js  c++  java
  • BZOJ 3123 SDOI2013 森林

    首先对于查询操作就是裸的COT QAQ

    在树上DFS建出主席树就可以了

    对于连接操作,我们发现并没有删除

    所以我们可以进行启发式合并,每次将小的树拍扁插入大的树里并重构即可

    写完了之后第一个和第二个点迷のRE

    然后又重新写了一遍就A了(并不知道为什么,难道第一遍写挫了?

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
     
    const int maxn=100010;
    int T,n,m,Q,u,v,k,lca,w;
    int ans=0;
    char ch;
    int p[maxn];
    int fa[maxn],dep[maxn],sz[maxn];
    int anc[maxn][20];
    int h[maxn],cnt=0;
    struct edge{
        int to,next;
    }G[maxn<<1];
    void add(int x,int y){++cnt;G[cnt].to=y;G[cnt].next=h[x];h[x]=cnt;}
    int ufs(int x){return fa[x]==x?x:fa[x]=ufs(fa[x]);}
     
    int a[maxn];
    struct val{
        int v,id;
    }c[maxn];
    bool cmpv(const val &A,const val &B){return A.v<B.v;}
    bool cmpid(const val &A,const val &B){return A.id<B.id;}
     
    int tot=0,rt[maxn];
    struct Seg_Tree{
        int L,R,v;
    }t[11000010];
     
    void read(int &num){
        num=0;ch=getchar();
        while(ch<'!')ch=getchar();
        while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
    }
    void build(int &o,int L,int R){
        o=++tot;
        if(L==R)return;
        int mid=(L+R)>>1;
        build(t[o].L,L,mid);
        build(t[o].R,mid+1,R);
    }
    void modify(int &o,int now,int L,int R,int p){
        t[++tot]=t[now];o=tot;
        if(L==R){t[o].v++;return;}
        int mid=(L+R)>>1;
        if(p<=mid)modify(t[o].L,t[now].L,L,mid,p);
        else modify(t[o].R,t[now].R,mid+1,R,p);
        t[o].v=t[t[o].L].v+t[t[o].R].v;
    }
    void DFS(int u,int f){
        anc[u][0]=f;
        modify(rt[u],rt[f],1,m,c[u].v);
        for(int i=1;i<=18;++i){
            if(anc[u][i-1]!=0){
                int a=anc[u][i-1];
                anc[u][i]=anc[a][i-1];
            }else anc[u][i]=0;
        }
        for(int i=h[u];i;i=G[i].next){
            int v=G[i].to;
            if(v==f)continue;
            dep[v]=dep[u]+1;
            DFS(v,u);
        }return;
    }
    int LCA(int p,int q){
        if(dep[p]<dep[q])swap(p,q);
        int d=dep[p]-dep[q];
        for(int i=18;i>=0;--i){
            if(d>>i&1)p=anc[p][i];
        }
        if(p==q)return p;
        for(int i=18;i>=0;--i){
            if(anc[p][i]!=anc[q][i]&&anc[p][i]!=0)p=anc[p][i],q=anc[q][i];
        }return anc[p][0];
    }
    int ask(int u,int v,int lca,int L,int R,int k){
        if(L==R)return L;
        int mid=(L+R)>>1;
        int now=t[t[u].L].v+t[t[v].L].v-2*t[t[lca].L].v+(w<=mid&&w>=L);
        if(k>now)return ask(t[u].R,t[v].R,t[lca].R,mid+1,R,k-now);
        else return ask(t[u].L,t[v].L,t[lca].L,L,mid,k);
    }
    int main(){
        read(T);read(n);read(m);read(Q);
        for(int i=1;i<=n;++i)read(c[i].v),c[i].id=i,a[i]=c[i].v;
        for(int i=1;i<=n;++i)fa[i]=i;
        for(int i=1;i<=m;++i){
            read(u);read(v);
            add(u,v);add(v,u);
            int d1=ufs(u),d2=ufs(v);
            if(d1!=d2)fa[d1]=d2;
        }m=0;
        sort(c+1,c+n+1,cmpv);sort(a+1,a+n+1);
        for(int i=1;i<=n;++i){
            if(i==1||a[i]!=a[i-1])c[i].v=++m,p[m]=a[i];
            else c[i].v=m;
        }
        sort(c+1,c+n+1,cmpid);
        build(rt[0],1,m);
        for(int i=1;i<=n;++i){
            if(ufs(i)==i)DFS(i,0);
            sz[ufs(i)]++;
        }
        while(Q--){
            ch=getchar();
            while(ch<'!')ch=getchar();
            if(ch=='Q'){
                scanf("%d%d%d",&u,&v,&k);
                u^=ans;v^=ans;k^=ans;
                lca=LCA(u,v);w=c[lca].v;
                //cout<<u<<' '<<v<<' '<<k<<endl;
                ans=p[ask(rt[u],rt[v],rt[lca],1,m,k)];
                printf("%d
    ",ans);
            }else{
                scanf("%d%d",&u,&v);
                u^=ans;v^=ans;
                //cout<<u<<' '<<v<<endl;
                int d1=ufs(u),d2=ufs(v);
                //cout<<d1<<' '<<d2<<endl;
                if(sz[d1]<sz[d2])swap(u,v),swap(d1,d2);
                sz[d1]+=sz[d2];
                if(d1!=d2)fa[d2]=d1;//d2->d1
                dep[v]=dep[u]+1;
                DFS(v,u);add(u,v);add(v,u);
            }
        }return 0;
    }
    

      

  • 相关阅读:
    编译原理学习导论-作者四川大学唐良(转)初学者必看
    Ajax在chrome浏览器中测试调用失败解决办法
    sublime中输入法输入框只能在一个位置
    第三次作业
    第二次作业
    第一次作业
    2018年 大一下学期第零次作业
    14,15周作业
    第七周作业
    第六周作业
  • 原文地址:https://www.cnblogs.com/joyouth/p/5392813.html
Copyright © 2011-2022 走看看