zoukankan      html  css  js  c++  java
  • HDU 4897 Little Devil I

    _(:3 ⌒゙)_ 调我半天,还是记录下吧。

    用轻重链可解决此题。

    用轻重链的方式给点重新编号后,建两棵线段树,一棵(sumTree)用于记录路径修改,另外一棵(markTree)用于记录邻边修改的点。

    然后维护下两棵树即可。

    注意,markTree修改时,要在sumTree上修改第一个点和最后一个点对应的重边,若修改的顶点为连接轻链的点,则sumTree对应边不修改。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #include<stack>
    #define ll long long
    #define INF 0x3f3f3f3f
    #define BUG printf("hehe!~
    ")
    #define lson(x) (x<<1)
    #define rson(x) (x<<1|1)
    #define y1 y123123
    using namespace std;
    
    const int N=100010;
    
    int n;
    vector<int> G[N];
    bool vis[N];
    int size[N],fa[N],mxson[N];
    int tot,num[N],top[N],pre[N],dep[N];
    int y1,y2;
    
    struct Node
    {
        int l,r;
        int rev;
        int sum;
    };
    
    void DFS(int x)
    {
        vis[x]=true;
        size[x]=1;
        int v;
        for(int i=0;i<G[x].size();++i) {
            v=G[x][i];
            if(!vis[v]) {
                fa[v]=x;
                DFS(v);
                size[x]+=size[v];
                if(size[v]>size[mxson[x]]) mxson[x]=v;
            }
        }
        vis[x]=false;
    }
    
    void make(int x,int depth,int tp)
    {
        ++tot;
        num[x]=tot;
        pre[tot]=x;
        top[x]=tp;
        dep[x]=depth;
        vis[x]=true;
        if(mxson[x]) {
            make(mxson[x],depth,tp);
        }
        int v;
        for(int i=0;i<G[x].size();++i) {
            v=G[x][i];
            if(!vis[v]&&v!=mxson[x]) {
                make(v,depth+1,v);
            }
        }
        vis[x]=false;
    }
    
    struct MyTree
    {
        Node T[N<<2];
        int _sum;//set 0
        void buildtree(int u,int L,int R)
        {
            if(L==R) {
                T[u].l=L;
                T[u].r=R;
                T[u].sum=0;
                return;
            }
            int mid=(L+R)>>1;
            T[u].l=L,T[u].r=R,T[u].sum=0,T[u].rev=0;
            buildtree(lson(u),L,mid);
            buildtree(rson(u),mid+1,R);
        }
    
        void maintain(int u,int L,int R)
        {
            int lc=lson(u),rc=rson(u);
            if(R>L) {
                T[u].sum=T[lc].sum+T[rc].sum;
            }
            if(T[u].rev) T[u].sum=T[u].r-T[u].l+1-T[u].sum;
        }
    
        void rever(int u,int L,int R)
        {
            //if(y1>y2) return;
            //if(L>R) return;
            if(y1<=L&&y2>=R) {
                T[u].rev^=1;
                T[u].sum=T[u].r-T[u].l+1-T[u].sum;
                return;
            }
            else {
                int mid=(L+R)>>1;
                if(y1<=mid) rever(lson(u),L,mid);
                if(y2>mid) rever(rson(u),mid+1,R);
            }
            maintain(u,L,R);
        }
    
        void querysum(int u,int L,int R,int re)
        {
            if(y1<=L&&y2>=R) {
                if(re) _sum+=T[u].r-T[u].l+1-T[u].sum;
                else _sum+=T[u].sum;
            } else {
                int mid=(L+R)>>1;
                if(y1<=mid) querysum(lson(u),L,mid,re^T[u].rev);
                if(y2>mid) querysum(rson(u),mid+1,R,re^T[u].rev);
            }
        }
    }sumTree,markTree;
    
    void reverpath(int x,int y)
    {
        if(dep[x]>dep[y]) swap(x,y);
        while(dep[x]<dep[y]) {
            y1=num[top[y]],y2=num[y];
            //cout<<x<<" "<<y<<" "<<y1<<"  "<<y2<<endl;
            if(y1<=y2)sumTree.rever(1,1,n);
            y=fa[top[y]];
        }
        while(top[x]!=top[y]) {
            y1=num[top[x]],y2=num[x];
            if(y1<=y2) sumTree.rever(1,1,n);
            y1=num[top[y]],y2=num[y];
            if(y1<=y2) sumTree.rever(1,1,n);
            x=fa[top[x]];
            y=fa[top[y]];
        }
        x=num[x],y=num[y];
        if(x>y) swap(x,y);
        y1=x+1,y2=y;
        //cout<<x<<" "<<y<<" "<<y1<<"  "<<y2<<endl;
        if(top[pre[y1]]==top[pre[y2]]&&y1<=y2) sumTree.rever(1,1,n);
    }
    
    void reveradj(int x,int y)
    {
        int ty,tx;
        if(dep[x]>dep[y]) swap(x,y);
        while(dep[x]<dep[y]) {
            y1=num[top[y]],y2=num[y];
            if(y1<=y2) markTree.rever(1,1,n);
            ty=num[y]+1;
            if(top[pre[ty]]==top[y]) {
                y1=ty,y2=ty;
                sumTree.rever(1,1,n);
            }
            y=fa[top[y]];
        }
        while(top[x]!=top[y]) {
            y1=num[top[y]],y2=num[y];
            if(y1<=y2) markTree.rever(1,1,n);
            ty=num[y]+1;
            if(top[pre[ty]]==top[y]) {
                y1=ty,y2=ty;
                sumTree.rever(1,1,n);
            }
            y1=num[top[x]],y2=num[x];
            if(y1<=y2) markTree.rever(1,1,n);
            tx=num[x]+1;
            if(top[pre[tx]]==top[x]) {
                y1=tx,y2=tx;
                sumTree.rever(1,1,n);
            }
            x=fa[top[x]];
            y=fa[top[y]];
        }
        //x=num[x],y=num[y];
        if(num[x]>num[y]) swap(x,y);
        y1=num[x],y2=num[y];
        if(y1<=y2) markTree.rever(1,1,n);
        //tx=num[x]-1;
        //if(top[pre[tx]]==top[x])
            //sumTree.rever(1,tx,tx);
        if(x!=top[x]) {
            y1=num[x],y2=num[x];
            sumTree.rever(1,1,n);
        }
        ty=num[y]+1;
        if(top[pre[ty]]==top[y]) {
            y1=ty,y2=ty;
            sumTree.rever(1,1,n);
        }
    }
    
    void query(int x,int y)
    {
        int ans=0;
        int lch,rch;
        if(dep[x]>dep[y]) swap(x,y);
        while(dep[x]<dep[y]) {
            y1=num[top[y]]+1,y2=num[y];
            sumTree._sum=0;
            if(y1<=y2) sumTree.querysum(1,1,n,0);
            ans+=sumTree._sum;
            sumTree._sum=0;
            y1=num[top[y]],y2=num[top[y]];
            sumTree.querysum(1,1,n,0);
            lch=sumTree._sum;
            markTree._sum=0;
            y1=num[top[y]],y2=num[top[y]];
            markTree.querysum(1,1,n,0);
            rch=markTree._sum;
            lch^=rch;
            y=fa[top[y]];
            markTree._sum=0;
            y1=num[y],y2=num[y];
            markTree.querysum(1,1,n,0);
            rch=markTree._sum;
            lch^=rch;
            ans+=lch;
        }
        while(top[x]!=top[y]) {//////////////////////////
            y1=num[top[y]]+1,y2=num[y];
            sumTree._sum=0;
            if(y1<=y2) sumTree.querysum(1,1,n,0);
            ans+=sumTree._sum;
            sumTree._sum=0;
            y1=num[top[y]],y2=num[top[y]];
            sumTree.querysum(1,1,n,0);
            lch=sumTree._sum;
            markTree._sum=0;
            y1=num[top[y]],y2=num[top[y]];
            markTree.querysum(1,1,n,0);
            rch=markTree._sum;
            lch^=rch;
            y=fa[top[y]];
            y1=num[y],y2=num[y];
            markTree._sum=0;
            markTree.querysum(1,1,n,0);
            rch=markTree._sum;
            lch^=rch;
            ans+=lch;
            y1=num[top[x]]+1,y2=num[x];
            sumTree._sum=0;
            if(y1<=y2) sumTree.querysum(1,1,n,0);
            ans+=sumTree._sum;
            sumTree._sum=0;
            y1=num[top[x]],y2=num[top[x]];
            sumTree.querysum(1,1,n,0);
            lch=sumTree._sum;
            markTree._sum=0;
            y1=num[top[x]],y2=num[top[x]];
            markTree.querysum(1,1,n,0);
            rch=markTree._sum;
            lch^=rch;
            x=fa[top[x]];
            markTree._sum=0;
            y1=num[x],y2=num[x];
            markTree.querysum(1,1,n,0);
            rch=markTree._sum;
            lch^=rch;
            ans+=lch;
            //x=fa[top[x]];
            //y=fa[top[y]];
        }
        if(num[x]>num[y]) swap(x,y);
        sumTree._sum=0;
        y1=num[x]+1,y2=num[y];
        if(y1<=y2) sumTree.querysum(1,1,n,0);
        ans+=sumTree._sum;
        printf("%d
    ",ans);
    }
    
    int main()
    {
        int _;
        int Q,c,a,b;
        cin>>_;
        while(_--) {
            scanf("%d",&n);
            tot=0;
            for(int i=0;i<=n;++i) G[i].clear();
            for(int i=1;i<n;++i) {
                scanf("%d%d",&a,&b);
                G[a].push_back(b);
                G[b].push_back(a);
            }
            fa[1]=-1;
            for(int i=1;i<=n;++i) mxson[i]=0;
            DFS(1);
            make(1,1,1);
            sumTree.buildtree(1,1,n);
            markTree.buildtree(1,1,n);
    
            scanf("%d",&Q);
            while(Q--) {
                scanf("%d%d%d",&c,&a,&b);
                //a=num[a];b=num[b];
                if(1==c) reverpath(a,b);
                else if(2==c) reveradj(a,b);
                else query(a,b);
            }
        }
    }
  • 相关阅读:
    Yeelink 初探
    Macbook被格式化之后
    linux 代码分析工具 gprof
    Writing Clean Code 读后感
    0 bug 读后感
    STM32 控制红外线收发
    HomeKit 与老旧设备
    树莓派控制红外线收发
    苹果没法删除部分照片的问题
    route处理
  • 原文地址:https://www.cnblogs.com/morimiya/p/3898118.html
Copyright © 2011-2022 走看看