3720: Gty的妹子树

树分块..

#include<bits/stdc++.h>
#define rep(i,k,n) for(int i=k;i<=(n);i++)
using namespace std;
const int N=60105;
int n,lastans=0,Size,w[N],m,belong[N],cnt=0,fa[N],ans;
struct E{
    int to,next;
    E(int to=0,int next=0):to(to),next(next){}
}edge[2][N<<1];
int head[2][N],tot[2];
void add(int x,int y,int op){
edge[op][++tot[op]]=E(y,head[op][x]);head[op][x]=tot[op];

if(!op){edge[op][++tot[op]]=E(x,head[op][y]);head[op][y]=tot[op];}
}
struct block{
    int size;int G[211];
    block(){size=0;}
    int query(int y){
        return size-(upper_bound(G+1,G+1+size,y)-G)+1;
    }
    void insert(int x){size++;
        for(int i=size;i>=1;i--){    //
            if(G[i-1]>x)G[i]=G[i-1];
            else {G[i]=x;break;}
        }
    }

    void modify(int x,int y){
       int pos=lower_bound(G+1,G+1+size,x)-G;
       G[pos]=y;
       for(int i=pos+1;i<=size;i++)if(G[i-1]>G[i])swap(G[i-1],G[i]);else break;
       for(int i=pos;i>=1;i--)if(G[i-1]>G[i])swap(G[i-1],G[i]);else break;
   }
}b[30100];
void dfs(int x){
    if(b[belong[fa[x]]].size>=Size){
    belong[x]=++cnt;
        b[cnt].insert(w[x]);
    add(belong[fa[x]],cnt,1);
    }
    else{int v=belong[fa[x]];
    belong[x]=v;
        b[v].insert(w[x]);
    }
    for(int i=head[0][x];i;i=edge[0][i].next){
        int v=edge[0][i].to;
        if(v!=fa[x]){
            fa[v]=x;dfs(v);
        }
    }
}
void Dfs(int x,int y){
    ans+=b[x].query(y);
    for(int i=head[1][x];i;i=edge[1][i].next){
        int v=edge[1][i].to;
        Dfs(v,y);
}
}
void solve(int x,int y){
    if(w[x]>y)ans++;
    for(int i=head[0][x];i;i=edge[0][i].next){
        int v=edge[0][i].to;
        if(v!=fa[x]){
            if(belong[v]==belong[x])solve(v,y);
            else Dfs(belong[v],y);
        }
    }
}
int main(){
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
    scanf("%d",&n);
    Size=sqrt(n)+1;
    int x,y,op;
    rep(i,1,n-1){
        scanf("%d%d",&x,&y);add(x,y,0);
    }rep(i,1,n)scanf("%d",&w[i]);
    dfs(1);
    cin>>m;
    rep(i,1,m){
        scanf("%d%d%d",&op,&x,&y);x^=lastans;y^=lastans;
        switch(op){
            case 0:
                ans=0;solve(x,y);
                lastans=ans;
                printf("%d\n",ans);
                break;
            case 1:
                b[belong[x]].modify(w[x],y);w[x]=y;
                break;
            case 2:
                w[++n]=y;fa[n]=x;
                add(x,n,0);
                dfs(n);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值