【动态树】hdu4897

两种操作,第一种一条路径的边的颜色取反,第二种将一半在这条路径中的边的颜色取反,询问一条路径黑边的数量。

每条边上再添一个代表点表示这条边的颜色,那么第一种操作就可以直接把要操作的链取出来,再打个标记,第二种操作可以给每个点加一个标记,表示这个点的虚边连出去的儿子会要变一次颜色,然后再直接把lca的父亲节点变个颜色,可以看到,当access的时候只有有限条边会从虚变实或者从实变虚,此时用父亲节点的标记修改一下即可。

需要注意的是access的时候实变虚或者虚变实都要考虑到修改,然后还有两种操作在边界的直接修改操作。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int l[300000],r[300000],rt[300000],sum[300000],cl[300000],cl2[300000],bj[300000],sw[300000],sw2[300000];
int size[300000];
int tail[300000],next[1000000],sora[1000000];
int n,ss,m;
inline void updata(int x)
{
    if (!x) return ;
    sum[x]=sum[l[x]]+sum[r[x]]+cl[x]*bj[x];
    size[x]=size[l[x]]+size[r[x]]+bj[x];
}
inline void swap(int x)
{
    if (!x) return ;
    sw[x]^=1;
    cl[x]^=1;
    sum[x]=size[x]-sum[x];
}
inline void swap2(int x)
{
    if (!x) return ;
    sw2[x]^=1;
    cl2[x]^=1;
}
inline void pushdown(int x)
{
    if (!x) return ;
    if (sw[x]) {
        if (l[x]) swap(l[x]);
        if (r[x]) swap(r[x]);
        sw[x]=0;
    }
    if (sw2[x]) {
        if (l[x]) swap2(l[x]);
        if (r[x]) swap2(r[x]);
        sw2[x]=0;
    }
}
inline void right(int x)
{
    int y=rt[x],z=rt[y];
    l[y]=r[x],rt[r[x]]=y;
    r[x]=y,rt[y]=x;
    if (l[z]==y) l[z]=x;else if (r[z]==y) r[z]=x;
    rt[x]=z;
    updata(y);
}
inline void left(int x)
{
    int y=rt[x],z=rt[y];
    r[y]=l[x],rt[l[x]]=y;
    l[x]=y,rt[y]=x;
    if (l[z]==y) l[z]=x;else if (r[z]==y) r[z]=x;
    rt[x]=z;
    updata(y);
}
inline void splay(int x)
{
    if (!x) return ;
    pushdown(x);
    for (int y,z;l[rt[x]]==x || r[rt[x]]==x;) {
        y=rt[x],z=rt[y];
        if (l[z]==y || r[z]==y) pushdown(z);
        pushdown(y),pushdown(x);
        if (l[y]==x) {
            if (l[z]==y) right(y);
            right(x);
        }
        else if (r[y]==x) {
            if (r[z]==y) left(y);
            left(x);
        }
    }
    updata(x);
}
inline void access(int x)
{
    if (!x) return ;
    bool flag=(x==2);
    splay(x);
    int tmp;
    for (tmp=l[x];r[tmp];tmp=r[tmp]) ;
    l[x]=0,updata(x);
    if (tmp) splay(tmp),cl[tmp]^=(cl2[x]*(!bj[x])),updata(tmp);
    for (;rt[x];) {
        int y=rt[x];
        splay(y);
        int tmp;
        for (tmp=x;r[tmp];tmp=r[tmp]) ;
        splay(tmp);
        cl[tmp]^=(cl2[y]*(!bj[y])),updata(tmp);
        tmp=l[y];
        for (;r[tmp];tmp=r[tmp]) ;
//        if (flag) cout<<tmp<<' '<<y<<endl;
        if (tmp) {
            splay(tmp);
            cl[tmp]^=(cl2[y]*(!bj[y])),updata(tmp);
        }
        splay(x),splay(y);
        l[y]=x,updata(y);
        splay(x);
    }
}
void origin()
{
    ss=n+n;
    for (int i=0;i<=n+n;i++) {
        l[i]=r[i]=rt[i]=sum[i]=bj[i]=0;
        sw[i]=sw2[i]=cl[i]=cl2[i]=size[i]=0;
        tail[i]=i,next[i]=0;
    }
    for (int i=1;i<=n;i++) bj[i]=0;
    for (int i=1;i<=n;i++) bj[i+n]=1;
}
void dfs(int x,int y)
{
    rt[x]=y;
    for (int i=x,ne;next[i];) {
        i=next[i],ne=sora[i];
        if (ne!=y) dfs(ne,x);
    }
}
void link(int x,int y)
{
    ++ss,next[tail[x]]=ss,tail[x]=ss,sora[ss]=y,next[ss]=0;
    ++ss,next[tail[y]]=ss,tail[y]=ss,sora[ss]=x,next[ss]=0;
}
int asklca(int x,int y)
{
    access(x),access(y);
    splay(x);
    if (rt[x]==0) return x;
    return rt[x];
}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    int t;
    scanf("%d",&t);
    for (;t;t--) {
        scanf("%d",&n);
        origin();
        for (int i=1;i<=n-1;i++) {
            int x,y;
            scanf("%d%d",&x,&y);
            link(x,n+i);
            link(n+i,y);
        }
        dfs(1,0);
        scanf("%d",&m);
        for (int i=1;i<=m;i++) {
            int c,L,R;
            scanf("%d%d%d",&c,&L,&R);
            int lca=asklca(L,R);
//            cout<<L<<' '<<R<<' '<<lca<<endl;
            if (L==lca) swap(L,R);
            if (1==c) {
                if (L==R) continue;
                if (R==lca) {
                    access(L);
                    access(lca);
                    splay(L),swap(L);
                    continue;
                }
                access(L);
                access(R);
                access(lca);
                splay(R),swap(R);
                splay(L),swap(L);
            }
            else if (2==c) {
                if (L==R) {
                    access(L);
                    splay(L);
//                    swap2(L);
                    cl2[L]^=1,updata(L);
                    int tmp=r[L];
                    for (;l[tmp];tmp=l[tmp]) ;
                    splay(tmp);
                    cl[tmp]^=1,updata(tmp);
                    continue;
                }
                if (R==lca) {
                    access(L);
                    access(lca);
                    splay(L),swap2(L);
                    splay(lca),cl2[lca]^=1,updata(lca);
                    int tmp=r[lca];
                    for (;l[tmp];tmp=l[tmp]) ;
                    if (tmp) {
                        splay(tmp);
                        cl[tmp]^=1,updata(tmp);
                    }
                    splay(L),tmp=r[L];
                    for (;r[tmp];tmp=r[tmp]) ;
                    if (tmp) {
                        splay(tmp);
                        cl[tmp]^=1,updata(tmp);
                    }
                    continue;
                }
                access(L);
                access(R);
                access(lca);
                splay(R),swap2(R);
                splay(L),swap2(L);
                splay(lca),cl2[lca]^=1,updata(lca);
                int tmp=r[lca];
                for (;l[tmp];tmp=l[tmp]) ;
                if (tmp) {
                    splay(tmp);
                    cl[tmp]^=1,updata(tmp);
                }
                splay(L),tmp=r[L];
                for (;r[tmp];tmp=r[tmp]) ;
                if (tmp) {
                    splay(tmp);
                    cl[tmp]^=1,updata(tmp);
                }
                splay(R),tmp=r[R];
                for (;r[tmp];tmp=r[tmp]) ;
                if (tmp) {
                    splay(tmp);
                    cl[tmp]^=1,updata(tmp);
                }
            }
            else if (3==c) {
                if (L==R) {
                    printf("0\n");
                    continue;
                }
                if (R==lca){
                    access(L);
                    access(lca);
                    splay(L);
                    int tmp=L;
                    for (;r[tmp];tmp=r[tmp]) ;
                    splay(tmp);
                    int ans=sum[tmp]-cl[tmp]+(cl[tmp]^cl2[lca]);
                    printf("%d\n",ans);
                    continue;
                }
                access(L);
                access(R);
                access(lca);
                splay(L),splay(R),splay(lca);
                for (;r[L];L=r[L]) ;splay(L);
                for (;r[R];R=r[R]) ;splay(R);
//                cout<<L<<' '<<R<<' '<<cl[L]<<' '<<cl[R]<<endl;
//                cout<<sum[L]<<' '<<sum[R]<<endl;
                int ans=sum[L]+sum[R]-cl[L]-cl[R]+(cl[L]^cl2[lca])+(cl[R]^cl2[lca]);
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值