NC215082. 树
描述
输入描述
第一行两个整数 n q,表示n个结点,q次操作。
第二行n个整数,表示每个点的权值。
接下来n - 1行两个整数,u v,表示u到v有一条无向边(保证数据构成一颗树)。
接下来q行,每行为题目描述提到的的3种格式之一,表示一次操作。
输出描述
按照输入顺序,对于每个1操作,输出一行一个整数表示对应的和。
示例1
输入:
7 5 1 1 1 1 1 1 1 1 2 1 3 2 4 2 5 3 6 3 7 2 3 1 3 1 1 1 2 1 3 1 6
输出:
4 7 2
C++(clang++11) 解法, 执行用时: 1109ms, 内存消耗: 100216K, 提交时间: 2020-12-18 20:14:45
#include<iostream> #include<vector> using namespace std; #define ll long long struct madoka{ ll l; ll r; ll sum; ll f; }ma[2000007]; ll n,q,a[1000007],u,v,cnt,op,vis[1000007],pos[1000007],son[1000007]; ll res[1000007],fa[1000007]; vector<ll>ho[1000007]; void dfs(ll p,ll f){ vis[p]=++cnt; pos[cnt]=p; fa[p]=f; for(int i=0;i<ho[p].size();i++){ ll to=ho[p][i]; if(to==f)continue; dfs(to,p); } son[p]=cnt; } void build(ll l,ll r,ll k){ ma[k].l=l; ma[k].r=r; if(l==r){ ma[k].sum=a[pos[l]]; return; } ll mid=(l+r)/2; build(l,mid,k*2); build(mid+1,r,k*2+1); ma[k].sum=ma[k*2].sum+ma[k*2+1].sum; return; } void down(ll k){ if(ma[k].f!=0&&ma[k].l!=ma[k].r){ ma[k*2].f+=ma[k].f; ma[k*2+1].f+=ma[k].f; ma[k*2].sum+=(ma[k*2].r-ma[k*2].l+1)*ma[k].f; ma[k*2+1].sum+=(ma[k*2+1].r-ma[k*2+1].l+1)*ma[k].f; ma[k].f=0; } } void up(ll k,ll l,ll r,ll z){ down(k); if(l<=ma[k].l&&ma[k].r<=r){ ma[k].sum+=(ma[k].r-ma[k].l+1)*z; ma[k].f+=z; return; } ll mid=(ma[k].l+ma[k].r)/2; if(l<=mid){ up(k*2,l,r,z); } if(mid<r){ up(k*2+1,l,r,z); } ma[k].sum=ma[k*2].sum+ma[k*2+1].sum; } ll qry(ll k,ll l,ll r){ down(k); if(l<=ma[k].l&&ma[k].r<=r){ return ma[k].sum; } ll mid=(ma[k].l+ma[k].r)/2,ans=0; if(l<=mid){ ans+=qry(k*2,l,r); } if(mid<r){ ans+=qry(k*2+1,l,r); } return ans; } int main() { scanf("%lld%lld",&n,&q); for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); } for(int i=1;i<n;i++){ scanf("%lld%lld",&u,&v); ho[u].push_back(v); ho[v].push_back(u); } dfs(1,0); build(1,n,1); while(q--){ scanf("%lld",&op); if(op==1){ scanf("%lld",&u); printf("%lld\n",qry(1,vis[u],son[u])+res[fa[u]]); } else if(op==2){ scanf("%lld%lld",&u,&v); up(1,vis[u],son[u],v); } else{ scanf("%lld%lld",&u,&v); if(u==1)up(1,vis[u],vis[u],(ho[u].size()+1)*v); else up(1,vis[u],vis[u],ho[u].size()*v); res[u]+=v; } } }