题目链接:Ka Chang
题解:把每层的个数分块,当修改的那层个数大于block时直接保存贡献,小于block时暴力用树状数组维护
#include<string.h> #include<bits/stdc++.h> #include<algorithm> #include<queue> #define ll long long #define pb push_back using namespace std; #define INF 0xffffff #define MAXN 300010 const int N=1e5+5; vector<int>g[N],dep[N],p; int block,in[N],out[N],n,q,cnt; ll b[N],an[N]; int lowbit(int x) { return x&-x; } void add(int x,int y) { while(x<=n) { b[x]+=y; x+=lowbit(x); } } ll sum(int x) { ll ans=0; while(x) { ans+=b[x]; x-=lowbit(x); } return ans; } void dfs(int v,int f,int d) { in[v]=++cnt; dep[d].pb(in[v]); for(int to:g[v]) { if(to!=f) { dfs(to,v,d+1); } } out[v]=cnt; } int main() { scanf("%d %d",&n,&q); for(int i=0;i<n-1;i++) { int u,v; scanf("%d %d",&u,&v); g[u].pb(v); g[v].pb(u); } dfs(1,0,0); block=sqrt(n); for(int i=0;i<n;i++) { if(dep[i].size()>block) { p.pb(i); } } while(q--) { int op,val,w; scanf("%d%d",&op,&val); if(op==1) { scanf("%d",&w); if(dep[val].size()>block)an[val]+=w; else { for(int i=0;i<dep[val].size();i++) { add(dep[val][i],w); } } } else { ll ans=sum(out[val])-sum(in[val]-1); for(int i=0;i<p.size();i++) { ans+=1ll*(upper_bound(dep[p[i]].begin(),dep[p[i]].end(),out[val])-lower_bound(dep[p[i]].begin(),dep[p[i]].end(),in[val]))*an[p[i]]; } printf("%lld ",ans); } } return 0; }