首页 > 其他 > 详细

HDU 4897 Little Devil I

时间:2014-08-07 22:52:55      阅读:613      评论:0      收藏:0      [点我收藏+]

_(: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!~\n")
#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\n",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);
        }
    }
}

 

HDU 4897 Little Devil I,布布扣,bubuko.com

HDU 4897 Little Devil I

原文:http://www.cnblogs.com/morimiya/p/3898118.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!