题解:

这一道题目和模板有不同的地方就是在于可以修改只有一条边和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\n",calc(x,y));
         }
     }
    return 0; 
}

 

posted on 2017-12-09 11:19  宣毅鸣  阅读(205)  评论(0编辑  收藏  举报