收藏
关注
一棵有N个节点的树,每个节点对应1个编号及1个权值,有2种不同的操作。
操作1:S x y z,表示如果编号为x的节点的权值 < y,则将节点x的权值加上z。(Single)
操作2:A x y z,表示如果编号为x的节点以及其所有子节点的权值平均值 < y,则将节点x及其所有子节点的权值加上z。(All)
给出树节点之间的关系,进行M次操作,问所有操作完成后,各个节点的权值为多少?
节点的编号为0 - N - 1,根节点的编号为0,并且初始情况下,根节点的权值也是0。
Input
第1行:2个数N, M,N为节点的数量,M为操作的数量(1 <= N, M <= 50000)。 第2 - N行:每行描述一个节点N[i]的信息,第2行对应编号为1的节点,第N行对应编号为N - 1的节点。具体内容为:每行2个数P[i], W[i]。P[i]为当前节点的父节点的编号,W[i]为当前节点的权值。(0 <= W[i] <= 10^5, P[i] < i) 第N + 1 - N + M行:每行表示一个操作,S x y z或A x y z,(0 <= y, z <= 10^5)。
Output
输出共N行,每行1个数W[i],表示经过M次后,编号为0 - N - 1的节点的权值。
Input示例
4 3 0 10 0 10 1 2 S 0 1 1 A 0 20 1 S 3 2 1
Output示例
2 11 11 3
思路:
很简单的一道树链剖分+线段树,写起来麻烦点。。代码量有点大,一不小心就打错了。找半天。。
实现代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define mid ll m = (l + r) >> 1 const ll M = 7e5+10; struct node{ ll to,next; }e[M]; ll n,m,cnt1,cnt,a[M]; ll sum[M<<2],lazy[M<<2],son[M],fa[M],head[M],siz[M],top[M],dep[M],tid[M],rk[M],mx[M]; void add(ll u,ll v){ e[++cnt1].to = v;e[cnt1].next = head[u];head[u] = cnt1; e[++cnt1].to = u;e[cnt1].next = head[v];head[v] = cnt1; } void dfs1(ll u,ll faz,ll deep){ dep[u] = deep; fa[u] = faz; siz[u] = 1; for(ll i = head[u];i;i=e[i].next){ ll v = e[i].to; if(v != fa[u]){ dfs1(v,u,deep+1); siz[u] += siz[v]; if(son[u] == -1||siz[v] > siz[son[u]]) son[u] = v; } } } void dfs2(ll u,ll t){ top[u] = t; mx[u] = cnt; tid[u] = cnt; rk[cnt] = u; cnt++; if(son[u] == -1) return; dfs2(son[u],t),mx[u] = max(mx[u],mx[son[u]]); for(ll i = head[u];i;i = e[i].next){ ll v = e[i].to; if(v != son[u]&&v != fa[u]) dfs2(v,v),mx[u]=max(mx[u],mx[v]); } } void scan_d ( ll& x , char c = 0 , ll flag = 0 ) { while ( ( c = getchar () ) != '-' && ( c < '0' || c > '9' ) ) ; if ( c == '-' ) flag = 1 , x = 0 ; else x = c - '0' ; while ( ( c = getchar () ) >= '0' && c <= '9' ) x = x * 10 + c - '0' ; if ( flag ) x = -x ; } void pushup(ll rt){ sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void build(ll l,ll r,ll rt){ if(l == r){ sum[rt] = a[rk[l]]; //cout<<"l: "<<l<<" sum: "<<sum[rt]<<" al: "<<rk[l]<<endl; return ; } mid; build(lson); build(rson); pushup(rt); } void update(ll p,ll c,ll l,ll r,ll rt){ if(l == r){ sum[rt] += c; return ; } mid; if(p <= m) update(p,c,lson); else update(p,c,rson); pushup(rt); } void pushdown(ll l,ll r,ll rt){ if(lazy[rt]){ mid; lazy[rt<<1]+=lazy[rt]; lazy[rt<<1|1]+=lazy[rt]; sum[rt<<1]+=lazy[rt]*(m-l+1); sum[rt<<1|1]+=lazy[rt]*(r-m); lazy[rt] = 0; } } ll query(ll L,ll R,ll l,ll r,ll rt){ if(L <= l&&R >= r){ return sum[rt]; } //cout<<l<<" "<<r<<endl; pushdown(l,r,rt); mid; ll ret = 0; if(L <= m) ret += query(L,R,lson); if(R > m) ret += query(L,R,rson); return ret; } void update1(ll L,ll R,ll c,ll l,ll r,ll rt){ if(l == r){ sum[rt]+=c; return ; } if(L <= l&&R >= r){ sum[rt]+=c*(r-l+1); lazy[rt]+=c; return ; } mid; pushdown(l,r,rt); if(L <= m) update1(L,R,c,lson); if(R > m) update1(L,R,c,rson); pushup(rt); } ll query1(ll p,ll l,ll r,ll rt){ if(l == r) return sum[rt]; pushdown(l,r,rt); mid; if(p <= m) return query1(p,lson); else return query1(p,rson); } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); ll u,w; cin>>n>>m; a[0] = 0; memset(son,-1,sizeof(son)); for(ll i = 1;i < n;i ++){ cin>>u>>w; add(u,i);a[i]=w; } dfs1(0,-1,1); dfs2(0,0); build(0,n-1,1); char op; ll x,y,z; while(m--){ cin>>op>>x>>y>>z; if(op == 'A'){ ll ans = query(tid[x],mx[x],0,n-1,1); double num = ans*1.0/(mx[x]-tid[x]+1); if(num < y) update1(tid[x],mx[x],z,0,n-1,1); } else{ ll ans = query1(tid[x],0,n-1,1); if(ans < y) update(tid[x],z,0,n-1,1); } } for(ll i = 0;i < n;i ++){ cout<<query1(tid[i],0,n-1,1)<<endl;; } return ; }