题意:
思路:
在二叉树里进行树上差分
建两个数组,差分数组b和权值数组a
给结点x的子树整体修改权值,只需修改b[x]即可
给除了结点x的所有结点修改权值,只需修改b[1]和b[x]即可
二叉树向上遍历树链,循环向上爬就行
最后求一次树上的前缀和即可
在求树上前缀和时,需要累加权值,并向下传递标记
Code:
#include <bits/stdc++.h>
using namespace std;
const int mxn=2e7+10;
int n,m,op,x;
int b[mxn],a[mxn],ans[mxn];
void dfs(int u,int fa){
if(u>n) return;
a[u]+=b[u];
ans[a[u]]++;
b[2*u]+=b[u];
b[2*u+1]+=b[u];
dfs(2*u,u);
dfs(2*u+1,u);
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>op>>x;
if(op==1){
b[x]++;
}else if(op==2){
b[1]++;
b[x]--;
}else if(op==3){
while(x){
a[x]++;
x/=2;
}
}else{
while(x){
a[x]--;
x/=2;
}
b[1]++;
}
}
dfs(1,0);
for(int i=0;i<=m;i++) cout<<ans[i]<<" ";
return 0;
}