4034: [HAOI2015]T2
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 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
1554438ksq2013 | 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\n",solvesum(x,1));break;
}
}
return 0;
}