Money out of Thin Air(樹鏈剖分)
阿新 • • 發佈:2018-12-19
【題目描述】 【思路】 樹鏈剖分,兩次dfs將重鏈轉換成連續區間,然後用線段樹維護區間和
#include<bits/stdc++.h> #define node tree[id] #define lson tree[id<<1] #define rson tree[id<<1|1] using namespace std; typedef long long ll; const int maxn=50005; struct Tree{ int left,right; ll lazy,sum; }; int n,m,cnt; int w[maxn]; vector<int> g[maxn]; int f[maxn],d[maxn],num[maxn],son[maxn]; int id[maxn],eid[maxn],rk[maxn],top[maxn]; Tree tree[maxn<<2]; void dfs(int u,int fa,int dep){ d[u]=dep; num[u]=1; for(int i=0;i<g[u].size();++i){ int v=g[u][i]; if(v!=fa){ dfs(v,u,dep+1); num[u]+=num[v]; if(son[u]==-1 || num[son[u]]<num[v]){ son[u]=v; } } } } void dfs2(int u,int t){ top[u]=t; id[u]=++cnt; rk[cnt]=u; if(son[u]!=-1){ dfs2(son[u],t); for(int i=0;i<g[u].size();++i){ int v=g[u][i]; if(v!=f[u] && v!=son[u]){ dfs2(v,v); } } } eid[u]=cnt; } void pushup(int id){node.sum=lson.sum+rson.sum;} void pushdown(int id){ if(node.lazy && node.left!=node.right){ lson.sum+=(lson.right-lson.left+1)*node.lazy; lson.lazy+=node.lazy; rson.sum+=(rson.right-rson.left+1)*node.lazy; rson.lazy+=node.lazy; node.lazy=0; } } void build(int id,int le,int ri){ node.left=le; node.right=ri; node.lazy=0; if(le==ri){ node.sum=w[rk[le]]; return; } int mid=(le+ri)>>1; build(id<<1,le,mid); build(id<<1|1,mid+1,ri); pushup(id); } ll query(int id,int le,int ri){ if(node.left==le && node.right==ri){ return node.sum; } pushdown(id); int mid=(node.left+node.right)>>1; if(ri<=mid) return query(id<<1,le,ri); else if(le>mid) return query(id<<1|1,le,ri); else return query(id<<1,le,mid)+query(id<<1|1,mid+1,ri); } void update(int id,int le,int ri,ll val){ if(node.left==le && node.right==ri){ node.sum+=val*(node.right-node.left+1); node.lazy+=val; return; } pushdown(id); int mid=(node.left+node.right)>>1; if(ri<=mid) update(id<<1,le,ri,val); else if(le>mid) update(id<<1|1,le,ri,val); else{ update(id<<1,le,mid,val); update(id<<1|1,mid+1,ri,val); } pushup(id); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n-1;++i){ scanf("%d%d",&f[i],&w[i]); son[i]=-1; int u=i,v=f[i]; g[u].push_back(v); g[v].push_back(u); } f[0]=son[0]=-1; dfs(0,-1,0); dfs2(0,0); build(1,1,n); while(m--){ char op[2]; int x,y,z; scanf("%s%d%d%d",op,&x,&y,&z); if(op[0]=='S'){ ll now=query(1,id[x],id[x]); if(now<y) update(1,id[x],id[x],z); } else{ ll now=query(1,id[x],eid[x]); if(now<(ll)y*num[x]) update(1,id[x],eid[x],z); } } for(int i=0;i<n;++i){ printf("%lld\n",query(1,id[i],id[i])); } return 0; }