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
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; }