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
1 2
10 20
1
0 1 5
Sample Output
HINT
Source
传说中的树分块。。。
将树分块,如果父亲节点所在的块已经满了,就新建一个块,否则加入父亲节点所在的块;插入节点类似(但这样分可以被卡)
同时在块中维护一个有序表,如果遇见整块就可以直接查询;
至于查询的话,直接dfs,如果碰到了与根节点同一个块的点就暴力统计(因为该块不一定全在根节点子树内),否则就直接统计整个块(易知该块子树包含在询问子树里面)
细节有点多。。。
// MADE BY QT666 #include<cstdio> #include<algorithm> #include<cmath> #include<iostream> #include<cstring> #include<vector> using namespace std; typedef long long ll; const int N=100050; int gi() { int x=0,flag=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*flag; } struct Block{ int a[210],size; void insert(int x){ size++;int i; for(i=size;i>1&&a[i-1]>x;i--) a[i]=a[i-1]; a[i]=x; } void update(int x,int y){ int pl=lower_bound(a+1,a+1+size,x)-a; for(;pl<size&&a[pl+1]<y;pl++) a[pl]=a[pl+1]; for(;pl>1&&a[pl-1]>y;pl--) a[pl]=a[pl-1]; a[pl]=y; } int query(int x){ int pl=upper_bound(a+1,a+1+size,x)-a; return size-pl+1; } }block[N]; int cnt,w[N],head[N],to[N],nxt[N],n,m,pos[N],tot,sz,ans,f[N]; vector<int>p[N]; void lnk(int x,int y){ to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt; to[++cnt]=x,nxt[cnt]=head[y],head[y]=cnt; } void build(int x,int fa){ f[x]=fa; if(block[pos[fa]].size==sz){ tot++;block[tot].insert(w[x]); pos[x]=tot;p[pos[fa]].push_back(tot); } else block[pos[fa]].insert(w[x]),pos[x]=pos[fa]; for(int i=head[x];i;i=nxt[i]){ int y=to[i]; if(y!=fa) build(y,x); } } void dfs_block(int x,int val){ ans+=block[x].query(val); for(int i=0;i<p[x].size();i++) dfs_block(p[x][i],val); } void dfs(int x,int val){ if(w[x]>val) ans++; for(int i=head[x];i;i=nxt[i]){ int y=to[i]; if(y!=f[x]){ if(pos[y]==pos[x]) dfs(y,val); else dfs_block(pos[y],val); } } } int main(){ freopen("1.in","r",stdin); freopen("1.out","w",stdout); n=gi(); for(int i=1;i<n;i++){ int x=gi(),y=gi();lnk(x,y); } for(int i=1;i<=n;i++) w[i]=gi(); sz=sqrt(n)+1;build(1,0); m=gi();ans=0; for(int i=1;i<=m;i++){ int flag=gi(),u=gi(),v=gi(); u^=ans,v^=ans; if(flag==0){ ans=0;dfs(u,v); printf("%d ",ans); } if(flag==1){ block[pos[u]].update(w[u],v); w[u]=v; } if(flag==2){ n++;w[n]=v;f[n]=u;lnk(u,n); if(block[pos[u]].size==sz){ tot++;block[tot].insert(w[n]); pos[n]=tot;p[pos[u]].push_back(tot); } else block[pos[u]].insert(w[n]),pos[n]=pos[u]; } } return 0; }