zoukankan      html  css  js  c++  java
  • BZOJ 4530 LCT/线段树合并

    //By SiriusRen
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=200050;
    int n,q,cnt,dfn[N],last[N],tree[N*16],lson[N*16],rson[N*16];
    int first[N],next[N],v[N],w[N],tot,root[N],fa[N],deep[N],f[N];
    struct Node{int xx,yy;char op[2];}node[N];
    void dfs(int x){
        dfn[x]=++cnt;
        for(int i=first[x];~i;i=next[i])
            if(v[i]!=fa[x])deep[v[i]]=deep[x]+1,fa[v[i]]=x,dfs(v[i]);
        last[x]=cnt;
    }
    void add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
    void Add(int x,int y){add(x,y),add(y,x);}
    void insert(int l,int r,int &pos,int num,int wei){
        if(!pos)pos=++cnt;
        if(l==r){tree[pos]=wei;return;}
        int mid=(l+r)>>1;
        if(mid<num)insert(mid+1,r,rson[pos],num,wei);
        else insert(l,mid,lson[pos],num,wei);
        tree[pos]=tree[lson[pos]]+tree[rson[pos]];
    }
    int query(int l,int r,int pos,int L,int R){
        if(!pos)return 0;
        if(l>=L&&r<=R)return tree[pos];
        int mid=(l+r)>>1;
        if(mid<L)return query(mid+1,r,rson[pos],L,R);
        else if(mid>=R)return query(l,mid,lson[pos],L,R);
        else return query(l,mid,lson[pos],L,R)+query(mid+1,r,rson[pos],L,R);
    }
    void merge(int pos1,int &pos2){
        if(!pos2)pos2=++cnt;
        tree[pos2]+=tree[pos1];
    //  printf("pos1=%d pos2=%d lson[pos1]=%d rson[pos1]=%d tree[pos]=%d
    ",pos1,pos2,lson[pos1],rson[pos1],tree[pos2]);
        if(lson[pos1])merge(lson[pos1],lson[pos2]);
        if(rson[pos1])merge(rson[pos1],rson[pos2]);
    }
    int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
    void dfs2(int x){
        if(lson[x])dfs2(lson[x]);
        if(rson[x])dfs2(rson[x]);
    }
    int main(){
        memset(first,-1,sizeof(first));
        scanf("%d%d",&n,&q),getchar();
        for(int i=1;i<=q;i++){
            scanf("%s%d%d",node[i].op,&node[i].xx,&node[i].yy);
            if(node[i].op[0]=='A')Add(node[i].xx,node[i].yy);
        }
        for(int i=1;i<=n;i++)if(!fa[i])dfs(i);
        cnt=0;
        for(int i=1;i<=n;i++)insert(1,n,root[i],dfn[i],1),f[i]=i;
        for(int i=1;i<=q;i++){
            if(node[i].op[0]=='A'){
                int fx=find(node[i].xx),fy=find(node[i].yy);
                if(fx!=fy)merge(root[fx],root[fy]),f[fx]=fy;
            }
            else{
                if(deep[node[i].xx]>deep[node[i].yy])swap(node[i].xx,node[i].yy);
                int fy=find(node[i].yy);
                long long temp=query(1,n,root[fy],dfn[node[i].yy],last[node[i].yy]);
                printf("%lld
    ",(tree[root[fy]]-temp)*temp);
            }
        }
    }
    //By SiriusRen
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=100050;
    int n,m,xx,yy,fa[N],ch[N][2],rev[N],size[N],Size[N],q[N],top;
    char op[10];
    bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    void push_up(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+1+Size[x];}
    void push_down(int x){if(rev[x])rev[ch[x][0]]^=1,rev[ch[x][1]]^=1,swap(ch[x][0],ch[x][1]),rev[x]=0;}
    void rotate(int p){
        int q=fa[p],y=fa[q],x=(ch[q][1]==p);
        ch[q][x]=ch[p][!x],fa[ch[q][x]]=q;
        ch[p][!x]=q,fa[p]=y;
        if(!isroot(q)){
            if(ch[y][1]==q)ch[y][1]=p;
            if(ch[y][0]==q)ch[y][0]=p;
        }fa[q]=p,push_up(q);
    }
    void splay(int x){
        q[++top]=x;
        for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i];
        while(top)push_down(q[top]),top--;
        for(int y=fa[x];!isroot(x);rotate(x),y=fa[x])if(!isroot(y)){
            if((ch[fa[y]][0]==y)^(ch[y][0]==x))rotate(x);
            else rotate(y);
        }push_up(x);
    }
    void access(int x){for(int t=0;x;t=x,x=fa[x])splay(x),Size[x]+=size[ch[x][1]]-size[t],ch[x][1]=t,push_up(x);}
    void makeroot(int x){access(x),splay(x),rev[x]^=1;}
    void link(int x,int y){makeroot(x),makeroot(y),fa[x]=y,Size[y]+=size[x],push_up(y);}
    void split(int x,int y){makeroot(x),access(y),splay(x);}
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)size[i]=1;
        while(m--){
            scanf("%s%d%d",op,&xx,&yy);
            if(op[0]=='A')link(xx,yy);
            else split(xx,yy),printf("%lld
    ",1ll*(Size[yy]+1)*(size[xx]-Size[yy]-1));
        }
    }
  • 相关阅读:
    【Dos-BatchPrograming】04
    【Dos-BatchPrograming】03
    【Dos-BatchPrograming】02
    【Dos-BatchPrograming】01
    【perl】01
    【Linux】Re04
    【Linux】Re03
    【Linux】Re02
    【Linux】Re01
    【C++】01
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6789310.html
Copyright © 2011-2022 走看看