• bzoj3862


    题解:

    这一道题目和模板有不同的地方就是在于可以修改只有一条边和i相邻

    于是我们还要记录与这个点相邻的点有没有改变

    代码:

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    const int N=400005;
    using namespace std;
    int fi[N],zz[N],ne[N],deep[N],fa[N],size[N],son[N],top[N];
    int x,y,opt,pos[N],q[N],cnt,h[N],tot,n,m,T;
    struct data
    {
        int w,b,delta,rev;
    }tr[N*4];
    void add(int x,int y)
    {
        ne[++tot]=fi[x];
        fi[x]=tot;
        zz[tot]=y;
    }
    void dfs(int x,int f)
    {
        size[x]=1; son[x]=0;
        deep[x]=deep[f]+1;
        for (int i=fi[x];i;i=ne[i])
         {
            if (zz[i]==f) continue;
            fa[zz[i]]=x;
            dfs(zz[i],x);
            size[x]+=size[zz[i]];
            if (size[zz[i]]>size[son[x]]) son[x]=zz[i];
         }
    }
    void dfs1(int x,int y)
    {
        pos[x]=++cnt;q[cnt]=x;top[x]=y;
        if (!son[x])return;
        dfs1(son[x],y);
        for (int i=fi[x];i;i=ne[i])
         if (zz[i]!=son[x]&&zz[i]!=fa[x])
          dfs1(zz[i],zz[i]);
    }
    void update(data &now,data l,data r)
    {
        now.w=l.w+r.w;
        now.b=l.b+r.b;
    }
    void clear(int now)
    {
        tr[now].b=tr[now].w=tr[now].rev=tr[now].delta=0;
    }
    void build(int now,int l,int r)
    {
        clear(now);
        if (l==r)
         {
            tr[now].b=0;
            if (l!=1) tr[now].w=1;
            return;
         }
        int mid=(l+r)/2;
        build(now<<1,l,mid);
        build(now<<1|1,mid+1,r);
        update(tr[now],tr[now<<1],tr[now<<1|1]);
    }
    void change(int now)
    {
        swap(tr[now].w,tr[now].b);
        tr[now].delta^=1;
    }
    void pushdown(int now)
    {
        if (tr[now].delta)
         {
            change(now<<1);
            change(now<<1|1);
            tr[now].delta=0;
         }
        if (tr[now].rev)
         {
            tr[now<<1].rev^=1; tr[now<<1|1].rev^=1;
            tr[now].rev=0;
         }
    }
    data query(int now,int l,int r,int ll,int rr)
    {
        if (ll<=l&&r<=rr) return tr[now];
        pushdown(now);
        int mid=(l+r)/2;data ans;int pd=0;
        if (ll<=mid) ans=query(now<<1,l,mid,ll,rr),pd=1;
        if (rr>mid)
         {
            if (pd) update(ans,ans,query(now<<1|1,mid+1,r,ll,rr));
            else ans=query(now<<1|1,mid+1,r,ll,rr);
         }
        return ans;
    }
    void qjchange(int now,int l,int r,int ll,int rr)
    {
        if (ll<=l&&r<=rr)
         {
            change(now);
            return;
         }
        int mid=(l+r)/2;
        pushdown(now);
        if (ll<=mid) qjchange(now<<1,l,mid,ll,rr);
        if (rr>mid) qjchange(now<<1|1,mid+1,r,ll,rr);
        update(tr[now],tr[now<<1],tr[now<<1|1]);
    }
    void reverse(int now,int l,int r,int ll,int rr)
    {
        if (ll<=l&&r<=rr)
         {
            tr[now].rev^=1;
            return;
         }
        pushdown(now);
        int mid=(l+r)/2;
        if (ll<=mid) reverse(now<<1,l,mid,ll,rr);
        if (rr>mid) reverse(now<<1|1,mid+1,r,ll,rr);
        update(tr[now],tr[now<<1],tr[now<<1|1]);
    }
    void solve(int x,int y)
    {
        while (top[x]!=top[y])
         {
            if (deep[top[x]]<deep[top[y]]) swap(x,y);
            qjchange(1,1,n,pos[top[x]],pos[x]);
            x=fa[top[x]];
         }
        if (deep[x]>deep[y]) swap(x,y);
        if (x==y) return;
        qjchange(1,1,n,pos[x]+1,pos[y]);
    }
    void paint(int x,int y)
    {
        bool pd=false;
        int t=0;
        while (top[x]!=top[y])
         {
            if (deep[top[x]]<deep[top[y]]) swap(x,y);
            reverse(1,1,n,pos[top[x]],pos[x]);
            if (son[x]) qjchange(1,1,n,pos[son[x]],pos[son[x]]);
            qjchange(1,1,n,pos[top[x]],pos[top[x]]);
            t=top[x]; x=fa[top[x]]; h[x]=t;
         }
        if (deep[x]>deep[y]) swap(x,y);
        reverse(1,1,n,pos[x],pos[y]); 
        qjchange(1,1,n,pos[x],pos[x]);
        if (son[y]) qjchange(1,1,n,pos[son[y]],pos[son[y]]);
    }
    int find(int now,int l,int r,int x)
    {
        if (x==0) return 0;
        if (l==r) return tr[now].rev;
        int mid=(l+r)/2;
        pushdown(now);
        if (x<=mid) return find(now<<1,l,mid,x);
        else return find(now<<1|1,mid+1,r,x);
    }
    int calc(int x,int y)
    {
        int ans=0;
        while (top[x]!=top[y])
         {
            if (deep[top[x]]<deep[top[y]]) swap(x,y);
            data t=query(1,1,n,pos[top[x]],pos[x]);
            data t1=query(1,1,n,pos[top[x]],pos[top[x]]);
            int k=find(1,1,n,pos[fa[top[x]]]);
            if (t1.b==1&&k) t.b--;
            if (t1.w==1&&k) t.b++;
            ans+=t.b;
            x=fa[top[x]];
         }
        if (deep[x]>deep[y]) swap(x,y);
        if (x==y) return ans;
        data t=query(1,1,n,pos[x]+1,pos[y]);
        return ans+t.b;
    }
    int main()
    {
        scanf("%d",&T);
        while (T--)
         {
             tot=cnt=0;
             memset(fi,0,sizeof fi);
            scanf("%d",&n);
            for (int i=1;i<n;i++)
             {
                scanf("%d%d",&x,&y);
                add(x,y);add(y,x);
             }
            dfs(1,0);dfs1(1,1);build(1,1,n);
            scanf("%d",&m);
            while (m--)
             {
                scanf("%d%d%d",&opt,&x,&y);
                if (opt==1) solve(x,y);
                if (opt==2) paint(x,y);
                if (opt==3) printf("%d
    ",calc(x,y));
             }
         }
        return 0; 
    }
  • 相关阅读:
    小程序登录页面
    小程序环境搭建
    js闭包
    作用域和作用域链及预解析
    高阶函数
    在.net core项目中,增加gulp打包任务
    阿里云部署docker-swarm 内网问题
    .net identity scaffold
    c#中对XML反序列化
    c# Reactive Extension中的FromEventPattern和FromEvent
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8010930.html
Copyright © 2020-2023  润新知