bzoj4034: [HAOI2015]T2

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

Sample Output

6
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\n",solvesum(x,1));break;
		}
	}
	return 0;
}


 

posted @ 2016-07-18 19:59  keshuqi  阅读(94)  评论(0编辑  收藏  举报