QTREE系列1,4,5,6,7 LCT

QTREE1

題意:

給出一棵N(N <= 10000)個點的樹,要求支持:
1.改變第i條邊的權值
2.求a->b上的最大邊權

解:

直接樹剖或LCT即可

代碼

1.LCT(660ms)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#define L(i) (T[i].s[0])
#define R(i) (T[i].s[1])
#define F(i) (T[i].fa)
#define For(i,j,k) for(register int i=(j);i<=(int)k;i++)
#define Forr(i,j,k) for(register int i=(j);i>=(int);i--)
#define Set(a,b) memset(a,b,sizeof(a))
#define Loc(i) (R(F(i))==i)
using namespace std;
const int N=20010;
inline void read(int &x){
    x=0;char c=getchar();int f=(c=='-');
    while(c<'0'||c>'9')c=getchar(),f!=(c=='-');
    while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
} 
int Begin[N],Next[N*2],to[N*2],e,n,m;
struct node{
    int s[2],fa,rev,v,mx;
};
struct LCT{
    node T[N];
    inline void clear(){Set(T,0);}
    inline bool isrt(int x){
        return R(F(x))!=x&&L(F(x))!=x;
    }
    inline void pushup(int x){
        T[x].mx=max(max(T[L(x)].mx,T[R(x)].mx),T[x].v);
    }
    inline void pushdown(int x){
        if(T[x].rev){
            T[x].rev=0,T[L(x)].rev^=1,T[R(x)].rev^=1;
            swap(L(x),R(x));
        }
    }
    inline void Pushdown(int x){
        if(!isrt(x))Pushdown(F(x));
        pushdown(x);
    }
    inline void Rotate(int x){
        int A=F(x),B=F(A),l=Loc(x),r=l^1,d=Loc(A);
        if(!isrt(A))T[B].s[d]=x;F(x)=B;
        F(A)=x,F(T[x].s[r])=A,T[A].s[l]=T[x].s[r],T[x].s[r]=A;
        pushup(A),pushup(x);
    }
    inline void splay(int x){
        Pushdown(x);
        while(!isrt(x)){
            if(!isrt(F(x)))Rotate(x);
            Rotate(x);
        }
        pushup(x);
    }
    inline void access(int x){
        for(int i=0;x;i=x,x=F(x))
            splay(x),R(x)=i,pushup(x);
    }
    inline void reverse(int x){
        access(x),splay(x),T[x].rev^=1;
    }
    inline int query(int x,int y){
        reverse(x),access(y),splay(y);
        return T[y].mx;
    }
    inline void modify(int x,int v){
        access(x),splay(x),T[x].v=v,pushup(x);
    }
}t;
char s[10];
void dfs(int u,int fa){
    for(int i=Begin[u];i;i=Next[i]){
        int v=to[i];
        if(v==fa)continue;
        t.T[v].fa=u;
        dfs(v,u);
    }
}
inline void add(int x,int y){
    to[++e]=y;Next[e]=Begin[x],Begin[x]=e;
}
int main(){
    int T;
    read(T);
    while(T--){
        t.clear();Set(Begin,0),e=0;
        read(n);
        For(i,1,n-1){
            int u,v,w;
            read(u),read(v),read(w);
            add(u,i+n),add(i+n,u),add(i+n,v),add(v,i+n);
            t.modify(i+n,w);
        }
        dfs(1,0);
        while(scanf("%s",s)!=EOF&&s[0]!='D'){
            int x,y;
            read(x),read(y);
            if(s[0]=='C')t.modify(x+n,y);
            else printf("%d\n",t.query(x,y));
        }
    }
    return 0;
}

樹剖(200ms 用了zkw線段樹,然後vjudge上就Rank1了):

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
#include<ctime>
#include<queue>
#define For(i,j,k) for(register int i=(j);i<=(int)k;i++)
#define Forr(i,j,k) for(register int i=(j);i>=(int)k;i--)
#define Rep(i,u) for(register int i=Begin[(u)],v=to[i];i;i=Next[i],v=to[i])
#define Set(a,b) memset((a),b,sizeof(a))
using namespace std;
const int N=10010,E=20010;
int Begin[N],Next[E],to[E],fa[N],siz[N],son[N],dep[N],w[N],e=1,top[N],cnt,n;
int d[N][3];
void read(int &x){
    x=0;char c=getchar();int f(0);
    while(c<'0'||c>'9'){c=getchar();if(c=='-')f=1;}
    while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();if(f)x=-x;
}
inline void add(int x,int y){to[++e]=y,Next[e]=Begin[x],Begin[x]=e;}
struct zkwtree{
    int T[N<<2],M;
    inline void clear(){Set(T,0);}
    inline void pushup(int x){T[x]=max(T[x<<1],T[x<<1|1]);}
    void Build(){for(M=1;M<=n+1;M<<=1);}
    void add(int x,int v){for(T[x+=M]=v,x>>=1;x;x>>=1)pushup(x);}
    int query(int s,int t){
        int ret=-0x3f3f3f3f;
        for(s+=M-1,t+=M+1;s^t^1;s>>=1,t>>=1){
            if(~s&1)ret=max(ret,T[s^1]);
            if(t&1)ret=max(ret,T[t^1]);
        }
        return ret;
    }
}t;
void dfs1(int u,int d){
    siz[u]=1;dep[u]=d;
    Rep(i,u)
        if(fa[u]!=v){
            fa[v]=u,dfs1(v,d+1),siz[u]+=siz[v];
            if(siz[v]>siz[son[u]])son[u]=v;
        }
} 
void dfs2(int u,int tp){
    top[u]=tp,w[u]=++cnt;
    if(son[u])dfs2(son[u],top[u]);
    Rep(i,u)
        if(son[u]!=v&&fa[u]!=v)
            dfs2(v,v);
}
void init(){
    read(n);
    Set(son,0),Set(Begin,0),Set(fa,0),e=1,cnt=0;
    For(i,1,n-1){
        read(d[i][0]),read(d[i][1]),read(d[i][2]);
        add(d[i][0],d[i][1]),add(d[i][1],d[i][0]);
    }
    dfs1(1,1);dfs2(1,1);
    t.clear();
    t.Build();
    For(i,1,n-1){
        if(dep[d[i][0]]>dep[d[i][1]])swap(d[i][0],d[i][1]);
        t.add(w[d[i][1]],d[i][2]);
    }
}
int Max(int x,int y){
    int tmp=-0x3f3f3f3f;
    for(;top[x]!=top[y];){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        tmp=max(tmp,t.query(w[top[x]],w[x]));
        x=fa[top[x]];
    }
    if (x==y)return tmp;
    if (dep[x]>dep[y])swap(x,y);
    return max(tmp,t.query(w[x]+1,w[y]));
}
void solve(){
    char s[10];
    while(scanf("%s",s)!=EOF){
        int x,y;
        if (s[0]=='D')break;
        read(x),read(y);
        if (s[0]!='Q')t.add(w[d[x][1]],y);
        else printf("%d\n",Max(x,y));
    }
}
int main(){
    int _;
    for(read(_);_;_--){
        init();
        solve();
    }
    return 0;
} 

QTREE4

題意

給定一棵N(N <= 100000)個節點的樹,邊有權值,一開始每個節點全白,要求支持:
1.給某個節點反色(黑->白 白->黑)
2.查詢最遠兩白點距離(特別的,只有一個白點答案爲0)

題解

邊權LCT維護子樹信息,pushup時注意討論。
對於一個節點維護這樣幾個值:
1.一個mutiset維護以該節點爲根的子樹中所有節點和它的最大,次大距離
2.一個mutiset維護以該節點爲根的子樹中最遠兩白點的路徑長度
3.以該點爲根的輔助樹中離在對應的實際的樹上最上面節點(其實就是輔助樹上最左節點)最遠白點距離
4..以該點爲根的輔助樹中離在對應的實際的樹上最下面節點(其實就是輔助樹上最右節點)最遠白點距離
最後該節點爲根的子樹中的答案就可以通過上面的值合併出來
在每次反色時更新答案即可

代碼

LCT(440ms)

#include<bits/stdc++.h>
#define For(i,j,k) for(int i=(j);i<=(int)k;i++)
#define Forr(i,j,k) for(int i=(j);i>=(int)k;i--)
#define Set(a,b) memset(a,b,sizeof(a))
#define Rep(i,u) for(int i=Begin[u],v=to[i];i;i=Next[i],v=to[i])
#define L(i) (T[i].s[0])
#define R(i) (T[i].s[1])
#define F(i) (T[i].fa)
#define lmx(i) (T[i].lmx)
#define rmx(i) (T[i].rmx)
#define mx(i) (T[i].mx)
#define Loc(i) (R(F(i))==i)
#define S(i) (T[i].sum)
using namespace std;
const int N=200010 ,INF=0x3f3f3f3f;
inline void read(int &x){
    x=0;char c=getchar();int f(0);
    while(c<'0'||c>'9')f|=(c=='-'),c=getchar();
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    if(f)x=-x;
}
int n,m,e,Begin[N>>1],Next[N],to[N],w[N],ans;
inline void add(int x,int y,int z){
    to[++e]=y,Next[e]=Begin[x],Begin[x]=e,w[e]=z;
}
inline int fir(multiset<int> &s){return s.size()?*s.rbegin():-INF;}
inline int sec(multiset<int> &s){return s.size()>1?*(++s.rbegin()):-INF;}
struct node{
    int s[2],lmx,rmx,mx,sum,len,w,fa; 
    multiset<int>chain,path;
};
struct LCT{
    node T[N];
    inline void init(){
        For(i,0,n)lmx(i)=rmx(i)=mx(i)=-INF;
    }
    inline void pushup(int x){
        S(x)=S(L(x))+S(R(x))+T[x].len;
        int cha=max(T[x].w,fir(T[x].chain));
        int l=max(cha,rmx(L(x))+T[x].len);
        int r=max(cha,lmx(R(x)));
        lmx(x)=max(lmx(L(x)),S(L(x))+T[x].len+r);
        rmx(x)=max(rmx(R(x)),S(R(x))+l);
        mx(x)=max(mx(L(x)),mx(R(x)));
        mx(x)=max(mx(x),fir(T[x].chain)+sec(T[x].chain));
        mx(x)=max(mx(x),fir(T[x].path));
        mx(x)=max(mx(x),max(rmx(L(x))+T[x].len+r,lmx(R(x))+l));
        if(T[x].w==0)mx(x)=max(mx(x),max(fir(T[x].chain),0));
    }
    inline bool isrt(int x){
        return R(F(x))!=x&&L(F(x))!=x;
    }
    inline void Rotate(int x){
        int A=F(x),B=F(A),l=Loc(x),r=l^1,d=Loc(A);
        if(!isrt(A))T[B].s[d]=x;F(x)=B;
        F(A)=x,F(T[x].s[r])=A,T[A].s[l]=T[x].s[r],T[x].s[r]=A;
        pushup(A);
    }
    inline void splay(int x){
        while(!isrt(x)){
            int y=F(x);
            if(isrt(y))Rotate(x);
            else if(Loc(x)^Loc(y))Rotate(x),Rotate(x);
            else Rotate(y),Rotate(x);
        }
        pushup(x);
    }
    inline void access(int x){
        for(int i=0;x;i=x,x=F(x)){
            splay(x);
            if(R(x))T[x].chain.insert(lmx(R(x))),T[x].path.insert(mx(R(x)));
            if(i)T[x].chain.erase(T[x].chain.find(lmx(i))),T[x].path.erase(T[x].path.find(mx(i)));
            R(x)=i,pushup(x);
        }
    }
    inline void modify(int x){
        access(x);splay(x),T[x].w=(T[x].w==0)?-INF:0;pushup(x);
        ans=mx(x);
    }
}t;
void dfs(int u){
    Rep(i,u)
        if(t.T[u].fa!=v)
            t.T[v].fa=u,t.T[v].len=w[i],dfs(v),
            t.T[u].chain.insert(t.T[v].lmx),t.T[u].path.insert(t.T[v].mx);
    t.pushup(u);
}
char s[10];
int main(){
    read(n);t.init();
    For(i,1,n-1){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w),add(v,u,w);
    }   
    dfs(1);ans=t.T[1].mx;
    read(m);
    while(m--){
        int x;
        scanf("%s",s);
        if(s[0]=='A'){
            if(ans<0)puts("They have disappeared.");
            else printf("%d\n",ans);
        }else read(x),t.modify(x);
    }
    return 0;
}

QTREE5

Qtree4弱化版
給定一棵N(N <= 100000)個節點的樹,邊權爲1,一開始每個節點全黑,要求支持:
1.給某個節點反色(黑->白 白->黑)
2.查詢最遠離v點最近白點距離(特別的,v是白點時答案爲0)

題解

與QTREE4類似
最大值變最小值
答案不合並
邊權是1

代碼

LCT(450ms)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<set>
#include<map>
#define For(i,j,k) for(int i=(j);i<=(int)k;i++)
#define Forr(i,j,k) for(int i=(j);i>=(int)k;i--)
#define Rep(i,u) for(int i=Begin[u],v=to[i];i;i=Next[i],v=to[i])
#define L(i) (T[i].s[0])
#define R(i) (T[i].s[1])
#define F(i) (T[i].fa)
#define lmi(i) (T[i].lmi)
#define rmi(i) (T[i].rmi)
#define mi(i) (T[i].mi)
#define S(i) (T[i].sum)
#define Loc(i) (R(F(i))==i)
#define getchar getchar_unlocked//卡常數
using namespace std;
const int N=200010,INF=100000000;
inline int fir(multiset<int> &s){return s.size()>0?(*s.begin()):INF;}
inline void read(int &x){
    x=0;char c=getchar();int f(0);
    while(c<'0'||c>'9')f|=(c=='-'),c=getchar();
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    if(f)x=-x;
}
int Begin[N],to[N],Next[N],e,n,m;
inline void add(int x,int y){
    to[++e]=y,Next[e]=Begin[x],Begin[x]=e;
}
struct node{
    int s[2],lmi,rmi,fa,sum,w,mi;
    multiset<int>chain;
};
struct LCT{
    node T[N];
    inline void init(){
        For(i,0,n)lmi(i)=T[i].w=rmi(i)=INF,T[i].chain.clear();
    }
    inline void pushup(int x){
        S(x)=S(L(x))+S(R(x))+1;
        int cha=min(T[x].w,fir(T[x].chain));
        int l=min(cha,rmi(L(x))+1),r=min(cha,lmi(R(x)));
        lmi(x)=min(lmi(L(x)),S(L(x))+1+r);
        rmi(x)=min(rmi(R(x)),S(R(x))+l);
        mi(x)=min(l,r);
    }
    inline bool isrt(int x){
        return R(F(x))!=x&&L(F(x))!=x;
    }
    inline void Rotate(int x){
        int A=F(x),B=F(A),l=Loc(x),r=l^1,d=Loc(A);
        if(!isrt(A))T[B].s[d]=x;F(x)=B;
        F(A)=x,F(T[x].s[r])=A,T[A].s[l]=T[x].s[r],T[x].s[r]=A;
        pushup(A);
    }
    inline void splay(int x){
        while(!isrt(x)){
            int y=F(x);
            //For(i,0,n)print(i);puts("");
            //printf("%d\n",isrt(y));
            if(isrt(y))Rotate(x);
            else if (Loc(y)^Loc(x))Rotate(x),Rotate(x);
            else Rotate(y),Rotate(x);
        }
        pushup(x);
    }
    inline void access(int x){
        for(int i=0;x;i=x,x=F(x)){
            splay(x);
            if(R(x))T[x].chain.insert(lmi(R(x)));
            if(i)T[x].chain.erase(T[x].chain.find(lmi(i)));
            R(x)=i,pushup(x);
        }
    }
    inline void modify(int x){
        access(x);splay(x);
        T[x].w=(T[x].w==0)?INF:0;
        pushup(x);
    }
    inline void query(int x){
        access(x);splay(x);
        printf("%d\n",mi(x)==INF?-1:mi(x));
    }
}t;
void dfs(int u){
    Rep(i,u)
        if(t.T[u].fa!=v){
            t.T[v].fa=u,dfs(v);
            t.T[u].chain.insert(t.T[v].lmi);
        }
    t.pushup(u);
}
int main(){
    int u,v;
    read(n);t.init();
    For(i,1,n-1){
        read(u),read(v);
        add(u,v),add(v,u);
    }
    dfs(1);
    read(m);
    while(m--){
        read(u),read(v);
        if(u==0)t.modify(v);        
        else t.query(v);
    }
    return 0;
}

QTREE6

題意

給定一棵N(N <= 100000)個節點的樹,一開始每個節點全黑,要求支持:
1.反色
2.查詢與之有聯繫的點的個數(兩點有聯繫當且僅當兩點路徑上所有點顏色相同)

題解

維護兩棵LCT,一棵黑樹森林一棵白樹森林
反色時在原來顏色的樹中斷開與父親節點的連邊,在更改後顏色樹中連接與父親節點的連邊,然後查詢就直接查詢該點所在樹大小即可,注意根節點的判斷

代碼

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
#include<set>
#define For(i,j,k) for(register int i=(j);i<=(int)k;i++)
#define Forr(i,j,k) for(register int i=(j);i>=(int)k;i--)
#define Rep(i,u) for(register int i=Begin[u],v=to[i];i;i=Next[i],v=to[i])
#define Set(a,b) memset(a,b,sizeof(a))
#define L(i) (T[i].s[0])
#define R(i) (T[i].s[1])
#define S(i) (T[i].sum)
#define ss(i) (T[i].ss)
#define F(i) (T[i].fa)
#define Loc(i) (R(F(i))==i)
#define getchar getchar_unlocked
using namespace std;
const int N=100001,INF=0x3f3f3f3f;
inline void read(int &x){
    x=0;char c=getchar();int f(0);
    while(c<'0'||c>'9')f|=(c=='-'),c=getchar();
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    if(f)x=-x;
}
int Begin[N],Next[N<<1],to[N<<1],e,col[N],fa[N];
inline void add(int x,int y){
    to[++e]=y,Next[e]=Begin[x],Begin[x]=e;
}
struct node {
    int s[2],sum,fa,ss;
};
struct LCT{
    node T[N];
    inline void pushup(int x){
        S(x)=S(L(x))+S(R(x))+ss(x)+1;
    }
    inline bool isrt(int x){
        return R(F(x))!=x&&L(F(x))!=x;
    }
    inline void Rotate(int x){
        int A=F(x),B=F(A),l=Loc(x),r=l^1,d=Loc(A);
        if(!isrt(A))T[B].s[d]=x;F(x)=B;
        F(A)=x,F(T[x].s[r])=A,T[A].s[l]=T[x].s[r],T[x].s[r]=A;
        pushup(A);
    }
    inline void splay(int x){
        while(!isrt(x)){
            int y=F(x);
            if(!isrt(y))Rotate(x);
            Rotate(x);
        }
        pushup(x);
    }
    inline void access(int x){
        for(int i=0;x;i=x,x=F(x)){
            splay(x);
            if(R(x))ss(x)+=S(R(x));
            if(i)ss(x)-=S(i);
            R(x)=i;pushup(x);
        }   
    }
    inline void cut(int x){
        access(x),splay(x);
        F(L(x))=0,L(x)=0,pushup(x);
    }
    inline void link(int x,int y){
        access(y),splay(y);splay(x);
        F(x)=y,R(y)=x,pushup(y);
    }
    inline int findrt(int x){
        access(x),splay(x);
        while(L(x))x=L(x);
        return x;
    }
    inline void query(int x){
        int c=col[x];
        x=findrt(x);
        splay(x);
        printf("%d\n",col[x]==c?S(x):S(R(x)));
    }
}t[2];
void dfs(int u){
    Rep(i,u)
        if(fa[u]!=v){
            fa[v]=u,t[1].T[v].fa=u,dfs(v);
            t[1].T[u].ss+=t[1].T[v].sum;
        }
    t[1].pushup(u);
}
int n,m;
int main(){
    int tp,u;
    read(n);
    For(i,1,n-1){
        int u,v;
        read(u),read(v);
        add(u,v),add(v,u);col[i]=1;
    }col[n]=1;
    dfs(1);
    read(m);
    while(m--){
        read(tp),read(u);
        if(tp==0)
            t[col[u]].query(u);
        else{ 
            if(fa[u])t[col[u]].cut(u),t[col[u]^1].link(u,fa[u]);
            col[u]^=1;
        }
    }
    return 0;
}

QTREE7

給定一棵N(N <= 100000)個節點的樹,一開始每個節點全黑,要求支持:
1.反色
2.查詢與之有聯繫的點中的最大權值(兩點有聯繫當且僅當兩點路徑上所有點顏色相同)
3.修改u的點權

題解

與QTREE6類似
多加一個mutiset就好了

代碼

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<set>
#include<vector>
#define L(i) (T[i].s[0])
#define R(i) (T[i].s[1])
#define F(i) (T[i].fa)
#define Mx(i) (T[i].Mx)
#define W(i) (T[i].w)
#define Loc(i) (R(F(i))==i)
#define For(i,j,k) for(int i=(j);i<=(int)k;i++)
#define Forr(i,j,k) for(int i=(j);i>=(int)k;i--)
#define Set(a,b) memset(a,b,sizeof(a));
#define Rep(i,u) for(int i=Begin[u],v=to[i];i;i=Next[i],v=to[i])
#define getchar getchar_unlocked
using namespace std;
const int N=100100,INF=0x3f3f3f3f;
inline int fir(multiset<int>&s){return s.size()?*s.rbegin():-INF;}
inline void read(int &x){
    x=0;char c=getchar();int f(0);
    while(c<'0'||c>'9')f|=(c=='-'),c=getchar();
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    if(f)x=-x;
}
int Begin[N],to[N<<1],Next[N<<1],e,fa[N],col[N];
inline void add(int x,int y){
    to[++e]=y,Next[e]=Begin[x],Begin[x]=e;
}
struct node{
    int s[2],fa,w,Mx;
    multiset<int>mx;
};
struct LCT{
    node T[N];
    inline void pushup(int x){
        Mx(x)=max(W(x),fir(T[x].mx));
        if(L(x))Mx(x)=max(Mx(x),Mx(L(x)));
        if(R(x))Mx(x)=max(Mx(x),Mx(R(x)));
    }
    inline bool isrt(int x){
        return R(F(x))!=x&&L(F(x))!=x;
    }
    inline void Rotate(int x){
        int A=F(x),B=F(A),l=Loc(x),r=l^1,d=Loc(A);
        if(!isrt(A))T[B].s[d]=x;F(x)=B;
        F(A)=x,F(T[x].s[r])=A,T[A].s[l]=T[x].s[r],T[x].s[r]=A;
        pushup(A);
    }
    inline void splay(int x){
        while(!isrt(x)){
            if(!isrt(F(x)))Rotate(x);
            Rotate(x);
        }
        pushup(x);
    }
    inline void access(int x){
        for(int i=0;x;i=x,x=F(x)){
            splay(x);
            if(R(x))T[x].mx.insert(Mx(R(x)));
            if(i)T[x].mx.erase(T[x].mx.find(Mx(i)));
            R(x)=i,pushup(x);
        }
    }
    inline void link(int x,int y){
        access(y),splay(y),splay(x);
        F(x)=y,R(y)=x,pushup(y);
    }
    inline void cut(int x){
        access(x),splay(x),L(x)=F(L(x))=0,pushup(x);
    }
    inline int findrt(int x){
        access(x),splay(x);
        while(L(x))x=L(x);
        return x;
    }
    inline void query(int x){
        int c=col[x];
        x=findrt(x);splay(x);
        printf("%d\n",c==col[x]?Mx(x):Mx(R(x)));
    }
    inline void modify(int x,int val){
        access(x),splay(x);
        W(x)=val;pushup(x);
    }
}t[2];
int n,m;
void dfs(int u){
    Rep(i,u)
        if(fa[u]!=v){
            fa[v]=t[col[v]].T[v].fa=u,dfs(v);
            t[col[v]].T[u].mx.insert(t[col[v]].T[v].Mx);
        }
    t[0].pushup(u);t[1].pushup(u);
}
int main(){
    read(n);
    For(i,1,n-1){
        int u,v;
        read(u),read(v);
        add(u,v),add(v,u);
    }
    For(i,1,n)read(col[i]);
    For(i,1,n)read(t[0].T[i].w),t[1].T[i].w=t[0].T[i].w;
    dfs(1);
    read(m);
    while(m--){
        int tp,u,v;
        read(tp),read(u);
        if(tp==0)t[col[u]].query(u);
        else if(tp==1){
            if(fa[u])t[col[u]].cut(u),t[col[u]^1].link(u,fa[u]);
            col[u]^=1;
        }else {
            read(v);
            t[0].modify(u,v),t[1].modify(u,v);
        }
    }
    return 0;
}

注意不要換根,因爲會改變樹形態

發佈了32 篇原創文章 · 獲贊 0 · 訪問量 6942
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章