BZOJ 3637: Query on a tree VI LCT_维护子树信息_点权转边权_好题

Code:

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <string>
#define setIO(s) freopen(s".in","r",stdin); 
#define maxn 100009
using namespace std;
int fat[maxn];
int n,m;
struct Graph{
    int head[maxn],to[maxn<<1],nex[maxn<<1],cnt;    
    void addedge(int u,int v){ nex[++cnt]=head[u],head[u]=cnt,to[cnt]=v; }  
    void dfs(int u,int father){
        fat[u]=father;
        for(int v=head[u];v;v=nex[v]) if(to[v]!=father) dfs(to[v],u);
    }
    void Build(){
        for(int i=1;i<n;++i){
            int a,b;
            scanf("%d%d",&a,&b), addedge(a,b),addedge(b,a); 
        }
        dfs(1,0);
    }
}G;
int col[maxn];       
struct LCT{
    int ch[maxn][2],f[maxn];
    int siz[maxn],son[maxn];
    int get(int x){ return ch[f[x]][1]==x; }
    int lson(int x){ return ch[x][0];}
    int rson(int x){ return ch[x][1];}
    int isRoot(int x){ return !(ch[f[x]][0]==x||ch[f[x]][1]==x); }
    void pushup(int x){ siz[x]=siz[lson(x)]+siz[rson(x)]+son[x]+1; }
    void rotate(int x)
    {
        int old=f[x],oldf=f[old],which=get(x);
        if(!isRoot(old)) ch[oldf][ch[oldf][1]==old]=x; 
        ch[old][which]=ch[x][which^1],f[ch[old][which]]=old;
        ch[x][which^1]=old,f[old]=x,f[x]=oldf;
        pushup(old),pushup(x);
    }
    void splay(int x)
    {
        int u=x;
        while(!isRoot(u)) u=f[u];
        u=f[u];
        for(int fa;(fa=f[x])!=u;rotate(x)) 
            if(f[fa]!=u) rotate(get(fa)==get(x)?fa:x);
    }
    void Access(int x){
        for(int y=0;x;y=x,x=f[x])
            splay(x),son[x]=son[x]+siz[ch[x][1]]-siz[y],ch[x][1]=y,pushup(x);
    }
    void cut(int a,int b){        
        if(!a) return; 
        Access(b),splay(b),ch[b][0]=f[ch[b][0]]=0,pushup(b);             
    }
    void link(int a,int b)
    {                    
        if(!a) return; 
        Access(a),splay(a),Access(b),splay(b);
        f[b]=a,ch[a][1]=b,pushup(a);
    }
    int findRoot(int a){
        Access(a),splay(a);
        while(ch[a][0]) a=ch[a][0];
        return a;
    }
}tree[2];
int main(){
    //setIO("input");
    scanf("%d",&n),G.Build();
    for(int i=2;i<=n;++i) tree[0].link(fat[i],i); 
    int opt,a;
    scanf("%d",&m);
    for(int i=1;i<=m;++i){
        scanf("%d%d",&opt,&a);
        if(opt==1) {
            tree[col[a]].cut(fat[a],a),col[a]^=1,tree[col[a]].link(fat[a],a);
        }
        if(opt==0) {
            int x=tree[col[a]].findRoot(a);
            tree[col[a]].splay(x);
            if(col[x]==col[a]) printf("%d\n",tree[col[a]].siz[x]);
            else printf("%d\n",tree[col[a]].siz[tree[col[a]].ch[x][1]]); 
        }
    }
    return 0;
}

  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值