给一颗树,两种操作,一种把同一层的点权值加上v,另一种求一点下的子树权值和。
按层数中点个数分块,小块直接暴力把所有点用bit更新,大块把层的值存下来。
询问的时候子树权值和为bit中的值以及其下面的点在大块中的值,下面中的点在大块中的值用二分实现。
#include <bits/stdc++.h> #include <unordered_set> #include <unordered_map> #define pb push_back #define mp make_pair #define x first #define y second #define rep(i,x,y) for(i=x;i<=y;i++) #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define up rt,rt<<1,rt<<1|1 #define mem(x) memset(x,0,sizeof(x)) #define mem1(x) memset(x,-1,sizeof(x)) #define LMissher using namespace std; typedef long long ll; typedef double db; const int M = 1e5+7; const double pi = acos(-1); const int inf = 2147483647; const int mod = 1e9+7; int n,q,i; int cnt,head[M],tot,dep; vector<int> d[M]; vector<int> lg; int in[M],out[M]; ll ans[M],c[M]; void init(){ tot=cnt=0; mem1(head); } struct edge { int v,nex; }e[M<<1]; void add(int u,int v){ e[++cnt].v=v;e[cnt].nex=head[u]; head[u]=cnt; } void dfs(int u,int fa,int de){ dep=max(de,dep); in[u]=++tot; d[de].pb(in[u]); for(int j=head[u];~j;j=e[j].nex){ int v=e[j].v; if(v==fa) continue; dfs(v,u,de+1); } out[u]=tot; } void update(int x,ll v){ for(;x<=n;x+=x&(-x)){ c[x]+=v; } } ll query(int x){ ll tmp=0; for(;x;x-=x&(-x)) tmp+=c[x]; return tmp; } int main(){ #ifdef LMissher freopen("1.in","r",stdin); freopen("1.out","w",stdout); #endif init(); scanf("%d%d",&n,&q); rep(i,1,n-1){ int from,to; scanf("%d%d",&from,&to); add(from,to);add(to,from); } dep=0; dfs(1,-1,0); int block=1<<12; rep(i,0,dep){ if(d[i].size()>block) lg.pb(i); } int op,l,v,rt; while(q--){ scanf("%d",&op); if(op==1){ scanf("%d%d",&l,&v); if(d[l].size()>block) ans[l]+=1ll*v; else{ for(i=0;i<d[l].size();i++){ update(d[l][i],v*1ll); } } } else{ scanf("%d",&rt); ll aa=query(out[rt])-query(in[rt]-1); for(i=0;i<lg.size();i++){ aa+=(upper_bound(d[lg[i]].begin(),d[lg[i]].end(),out[rt])-lower_bound(d[lg[i]].begin(),d[lg[i]].end(),in[rt]))*ans[lg[i]]; } printf("%lld\n",aa); } } return 0; }
原文地址:https://www.cnblogs.com/LMissher/p/9611076.html
时间: 2024-09-28 12:12:52