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。
解题报告
对于这个题,直接以父亲所在块的\(size\)分块,如果父亲节点\(size<B\),直接把当前节点加入块中,否则新建一个块,\(B\)为设定的块的大小,对于插入做相同的判断即可.我们维护一个块内的节点的权值的单调性,每一次询问相同块内暴力找,如果遍历到了其他块直接二分块内即可,对于块与块之间可以建一个新图,方便遍历使用.
对于修改操作,我们可以直接修改后sort,也可以利用单调性\(O(B)\)插入,推荐后面一种方法.
另外就是块大小的设定:本题中最优设定为 \(\sqrt{n*log}\),可以简单证明:插入为\(O(B)\),询问为 \(O(n*log(B)/B)\),总复杂度为 \(B+nlog(B)/B\),根据均值不等式 \(B\) 取 \(\sqrt{n*log}\)最优
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N=70005,B=631;
int n,fa[N],val[N],num=0,head[N],cnt=0,bel[N],Head[N],NUM=0,ans=0;
struct edge{int nxt,to;}a[N<<1],e[N<<1];
il void link(int x,int y){a[++num].nxt=head[x];a[num].to=y;head[x]=num;}
il void lenk(int x,int y){e[++NUM].nxt=Head[x];e[NUM].to=y;Head[x]=NUM;}
struct block{
int c[B+5],size;
il void insert(int x){
size++;RG int i=size;
for(i=size;i>=2 && x<=c[i-1];i--)c[i]=c[i-1];
c[i]=x;
}
il void upd(int x,int y){
RG int p=lower_bound(c+1,c+size+1,x)-c,i;
for(i=p;i<size;i++)c[i]=c[i+1];
for(i=size;i>=2 && y<=c[i-1];i--)c[i]=c[i-1];
c[i]=y;
}
il int query(int x){
int i=upper_bound(c+1,c+size+1,x)-c;
return size-i+1;
}
}b[6005];
il void dfs(RG int x){
if(b[bel[fa[x]]].size<B)bel[x]=bel[fa[x]],b[bel[x]].insert(val[x]);
else bel[x]=++cnt,b[cnt].insert(val[x]),lenk(bel[fa[x]],cnt);
for(RG int i=head[x],u;i;i=a[i].nxt){
u=a[i].to;if(u==fa[x])continue;
fa[u]=x;dfs(u);
}
}
il void btree(int x,int y){
ans+=b[x].query(y);
for(int i=Head[x],u;i;i=e[i].nxt){
u=e[i].to;btree(u,y);
}
}
il void qtree(int x,int y){
if(val[x]>y)ans++;
for(RG int i=head[x],u;i;i=a[i].nxt){
u=a[i].to;if(u==fa[x])continue;
if(bel[u]==bel[x])qtree(u,y);
else btree(bel[u],y);
}
}
void work()
{
int x,y;
scanf("%d",&n);
for(RG int i=1;i<n;i++){
scanf("%d%d",&x,&y);
link(x,y);link(y,x);
}
for(RG int i=1;i<=n;i++)scanf("%d",&val[i]);
dfs(1);
int m,flag;scanf("%d",&m);
while(m--){
scanf("%d%d%d",&flag,&x,&y);
x^=ans;y^=ans;
if(flag==0)ans=0,qtree(x,y),printf("%d\n",ans);
else if(flag==1){
b[bel[x]].upd(val[x],y);
val[x]=y;
}
else{
fa[++n]=x;val[n]=y;link(x,n);link(n,x);
if(b[bel[x]].size<B)bel[n]=bel[x],b[bel[x]].insert(y);
else bel[n]=++cnt,lenk(bel[x],cnt),b[cnt].insert(y);
}
}
}
int main()
{
work();
return 0;
}