4034: [HAOI2015]T2
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 2684 Solved: 843
Description
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
Input
第一行包含两个整数 N, M 。表示点数和操作数。
接下来一行 N 个整数,表示树中节点的初始权值。
接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。
再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操
作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
Output
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
Sample Input
5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3
Sample Output
6
9
13
9
13
HINT
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不
会超过 10^6 。
Source
1554438
ksq2013 | 4034 | Accepted | 15676 kb | 2760 ms | C++/Edit | 2537 B | 2016-07-18 19:59:13 |
#include<cstdio> #include<cstring> #include<iostream> using namespace std; typedef long long ll; int n,q,first[100100],val[100100]; ll col[400100],sum[400100]; struct Edge{int u,v,nxt;Edge(){nxt=0;}}e[200100]; int cnt,sz[100100],id[100100],mx[100100],fa[100100],blg[100100]; void dfs1(int x) { sz[x]=1; for(int i=first[x];i;i=e[i].nxt) if(e[i].v!=fa[x]){ fa[e[i].v]=x; dfs1(e[i].v); sz[x]+=sz[e[i].v]; } } void dfs2(int x,int tp) { blg[x]=tp; id[x]=mx[x]=++cnt; int k=0; for(int i=first[x];i;i=e[i].nxt) if(e[i].v!=fa[x]&&sz[e[i].v]>sz[k]) k=e[i].v; if(k){ dfs2(k,tp); mx[x]=max(mx[x],mx[k]); } for(int i=first[x];i;i=e[i].nxt) if(e[i].v!=fa[x]&&e[i].v!=k) {dfs2(e[i].v,e[i].v);mx[x]=max(mx[x],mx[e[i].v]);} } inline void pushdown(int k,int m) { if(col[k]){ col[k<<1]+=col[k]; col[k<<1|1]+=col[k]; sum[k<<1]+=(m-(m>>1))*col[k]; sum[k<<1|1]+=(m>>1)*col[k]; col[k]=0; } } void update(int s,int t,int k,int l,int r,ll p) { if(l<=s&&t<=r){ sum[k]+=p*(ll)(t-s+1); col[k]+=p; return; }pushdown(k,t-s+1); int m=(s+t)>>1; if(l<=m)update(s,m,k<<1,l,r,p); if(r>m)update(m+1,t,k<<1|1,l,r,p); sum[k]=sum[k<<1]+sum[k<<1|1]; } ll qsum(int s,int t,int k,int l,int r) { if(l<=s&&t<=r)return sum[k]; pushdown(k,t-s+1); int m=(s+t)>>1; ll res=0; if(l<=m)res+=qsum(s,m,k<<1,l,r); if(r>m)res+=qsum(m+1,t,k<<1|1,l,r); return res; } ll solvesum(int x,int f) { ll res=0; while(blg[x]!=blg[f]){ res+=qsum(1,n,1,id[blg[x]],id[x]); x=fa[blg[x]]; } res+=qsum(1,n,1,id[f],id[x]); return res; } int main() { scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%d",&val[i]); for(int i=1;i<=n-1;i++){ scanf("%d%d",&e[i].u,&e[i].v); e[i].nxt=first[e[i].u]; first[e[i].u]=i; e[i+n-1].u=e[i].v; e[i+n-1].v=e[i].u; e[i+n-1].nxt=first[e[i].v]; first[e[i].v]=i+n-1; } dfs1(1); dfs2(1,1); for(int i=1;i<=n;i++) update(1,n,1,id[i],id[i],val[i]); for(int i=1;i<=q;i++){ int d,x,y; scanf("%d",&d); switch(d){ case 1:scanf("%d%d",&x,&y);update(1,n,1,id[x],id[x],y);break; case 2:scanf("%d%d",&x,&y);update(1,n,1,id[x],mx[x],y);break; case 3:scanf("%d",&x);printf("%lld ",solvesum(x,1));break; } } return 0; }