Gty的妹子树(bzoj 3720)

Description

我曾在弦歌之中听过你,

檀板声碎,半出折子戏。

舞榭歌台被风吹去,

岁月深处尚有余音一缕……


Gty神(xian)犇(chong)从来不缺妹子……

他来到了一棵妹子树下,发现每个妹子有一个美丽度……

由于Gty很哲♂学,他只对美丽度大于某个值的妹子感兴趣。

他想知道某个子树中美丽度大于k的妹子个数。

某个妹子的美丽度可能发生变化……

树上可能会出现一只新的妹子……


维护一棵初始有n个节点的有根树(根节点为1),树上节点编号为1-n,每个点有一个权值wi。

支持以下操作:

0 u x          询问以u为根的子树中,严格大于x的值的个数。(u^=lastans,x^=lastans)

1 u x          把u节点的权值改成x。(u^=lastans,x^=lastans)

2 u x          添加一个编号为"当前树中节点数+1"的节点,其父节点为u,其权值为x。(u^=lastans,x^=lastans)

最开始时lastans=0。

Input

输入第一行包括一个正整数n(1<=n<=30000),代表树上的初始节点数。

接下来n-1行,每行2个整数u,v,为树上的一条无向边。

任何时刻,树上的任何权值大于等于0,且两两不同。

接下来1行,包括n个整数wi,表示初始时每个节点的权值。

接下来1行,包括1个整数m(1<=m<=30000),表示操作总数。

接下来m行,每行包括三个整数 op,u,v:

op,u,v的含义见题目描述。

保证题目涉及的所有数在int内。

Output

对每个op=0,输出一行,包括一个整数,意义见题目描述。

Sample Input

2
1 2
10 20
1
0 1 5

Sample Output

2
/*
  刚开始打算在dfs序上搞事情,然后发现不会动态维护,所以只能树上分块。
  先搞出一个块长len,在dfs时,超过这个len就重新划分一块,维护块之间的连通性。
  添加的时候可以超过len就更新一块新的,但是由于懒的写,所以直接添加的,导致跑到了10000+。 
*/
#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#define N 60010
using namespace std;
int w[N],head[N],fa[N],dep[N],bl[N],size[N],ind[N],vis[N],n,m,cnt,len;
struct node{int v,pre;}e[N*2];
vector<int> g[N],blo[N];
void add(int u,int v){
    e[++cnt].v=v;
    e[cnt].pre=head[u];
    head[u]=cnt;
}
void dfs(int x){
    for(int i=head[x];i;i=e[i].pre){
        if(e[i].v==fa[x]) continue;
        fa[e[i].v]=x;dep[e[i].v]=dep[x]+1;
        if(size[x]<len) size[bl[e[i].v]=bl[x]]++;
        else {
            g[bl[x]].push_back(bl[e[i].v]);
            g[bl[e[i].v]].push_back(bl[x]);
        }
        dfs(e[i].v);
    }
}
int query(int x,int y){
    int ans=0;
    if(bl[x]==x){
        ans+=blo[x].end()-upper_bound(blo[x].begin(),blo[x].end(),y);
        for(int i=0;i<g[bl[x]].size();i++){
            int v=g[bl[x]][i];
            if(dep[v]<dep[x]) continue;
            ans+=query(v,y);
        }
        return ans;
    }
    else {
        ans+=w[x]>y;
        for(int i=head[x];i;i=e[i].pre){
            if(fa[x]==e[i].v) continue;
            ans+=query(e[i].v,y);
        }
        return ans;
    }
}
void modify(int x,int y){
    int pos=lower_bound(blo[bl[x]].begin(),blo[bl[x]].end(),w[x])-blo[bl[x]].begin();
    w[x]=y;blo[bl[x]][pos]=y;
    sort(blo[bl[x]].begin(),blo[bl[x]].end());
}
void join(int x,int y){
    fa[++n]=x;w[n]=y;dep[n]=dep[x]+1;
    add(x,n);add(n,x);
    blo[bl[n]=bl[x]].push_back(y);
    sort(blo[bl[x]].begin(),blo[bl[x]].end());
}
int main(){
    scanf("%d",&n);
    //len=sqrt((double)n/log((double)n)*log(2));
    len=sqrt(n);
    for(int i=1;i<n;i++){
        int u,v;scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    for(int i=1;i<=n;i++)
        scanf("%d",&w[i]),size[i]=1,bl[i]=i;
    dfs(1);
    for(int i=1;i<=n;i++){
        blo[bl[i]].push_back(w[i]);
        if(!vis[bl[i]])vis[bl[i]]=1,ind[++ind[0]]=bl[i];
    }
    for(int i=1;i<=ind[0];i++)
        sort(blo[ind[i]].begin(),blo[ind[i]].end());
    scanf("%d",&m);int ans=0;
    for(int i=1;i<=m;i++){
        int opt,x,y;scanf("%d%d%d",&opt,&x,&y);
        x^=ans;y^=ans;
        if(opt==0) ans=query(x,y),printf("%d\n",ans);
        else if(opt==1) modify(x,y);
        else join(x,y);
    }
    return 0;
}

 

posted @ 2017-02-23 22:17  karles~  阅读(263)  评论(0编辑  收藏  举报