1. 程式人生 > >2018沈陽網絡賽J

2018沈陽網絡賽J

bsp pan dfs play typedef from 沈陽 fir \n

給一顆樹,兩種操作,一種把同一層的點權值加上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; }
View Code

2018沈陽網絡賽J