记录编号 160449 评测结果 AAAAAAAAAA
题目名称 [HAOI 2015]树上操作 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 3.028 s
提交时间 2015-04-27 15:25:35 内存使用 9.85 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iomanip>
#include<vector>
using namespace std;
typedef long long LL;
const int SIZEN=100010,SIZEM=200010;
int N,M;
class Edge{
public:
	int to;
	int nxt;
};
Edge edges[SIZEM];
int tot=0;
int head[SIZEN];
LL val[SIZEN];
LL lis_val[SIZEN];
int father[SIZEN];
int lis_fa[SIZEN];
int subsz[SIZEN];
int dfn[SIZEN];
int dfslis[SIZEN];
int timer=0;
int BN,Bsize;
int start[SIZEN],end[SIZEN];
int belong[SIZEN];
LL badd[SIZEN];//整个区间被加了多少
LL cgoal[SIZEN];//跳出块之前最后跳到哪里
LL cnum[SIZEN];//跳出块之前有多少个
LL csum[SIZEN];//跳出块之前的和(不计badd)
void calc_block(int k){
	for(int i=start[k];i<=end[k];i++) lis_val[i]+=badd[k];
	badd[k]=0;
	for(int i=start[k];i<=end[k];i++){
		int j=lis_fa[i];
		if(belong[j]!=k){
			cgoal[i]=i;
			cnum[i]=1;
			csum[i]=lis_val[i];
		}
		else{
			cgoal[i]=cgoal[j];
			cnum[i]=cnum[j]+1;
			csum[i]=csum[j]+lis_val[i];
		}
	}
}
void seg_add(int l,int r,LL w){
	if(belong[l]==belong[r]){
		for(int i=l;i<=r;i++){
			lis_val[i]+=w;
		}
		calc_block(belong[l]);
	}
	else{
		for(int k=belong[l]+1;k<belong[r];k++){
			badd[k]+=w;
		}
		for(int i=l;i<=end[belong[l]];i++) lis_val[i]+=w;
		for(int i=start[belong[r]];i<=r;i++) lis_val[i]+=w;
		calc_block(belong[l]);
		calc_block(belong[r]);
	}
}
LL query(int u){
	int k=dfn[u];
	LL ans=0;
	while(k){
		ans+=csum[k]+cnum[k]*badd[belong[k]];
		k=lis_fa[cgoal[k]];
	}
	return ans;
}
void work(void){
	int cmd;
	int x,a;
	for(int i=1;i<=M;i++){
		scanf("%d",&cmd);
		if(cmd==1){
			scanf("%d%d",&x,&a);
			seg_add(dfn[x],dfn[x],a);
		}
		else if(cmd==2){
			scanf("%d%d",&x,&a);
			seg_add(dfn[x],dfn[x]+subsz[x]-1,a);
		}
		else if(cmd==3){
			scanf("%d",&x);
			LL ans=query(x);
			printf("%lld\n",ans);
		}
	}
}
void make_block(void){
	for(int i=1;i<=N;i++){
		lis_val[dfn[i]]=val[i];
		lis_fa[dfn[i]]=dfn[father[i]];
	}
	Bsize=sqrt(1.0*N)+1;
	BN=1;start[1]=1;
	int tot=0;
	for(int i=1;i<=N;i++){
		belong[i]=BN;
		end[BN]=i;
		tot++;
		if(tot>=Bsize||i==N){
			BN++;
			start[BN]=i+1;
			tot=0;
		}
	}
	for(int i=1;i<=BN;i++) calc_block(i);
}
void DFS(int x){
	dfn[x]=++timer;
	dfslis[timer]=x;
	subsz[x]=1;
	for(int i=head[x];i!=-1;i=edges[i].nxt){
		Edge &e=edges[i];
		int u=e.to;
		if(u==father[x]) continue;
		father[u]=x;
		DFS(u);
		subsz[x]+=subsz[u];
	}
}
void addedge(int from,int to){
	edges[tot]=(Edge){to,head[from]};
	head[from]=tot;
	tot++;
}
void read(void){
	scanf("%d%d",&N,&M);
	int x;
	for(int i=1;i<=N;i++){
		scanf("%d",&x);
		val[i]=x;
	}
	int a,b;
	for(int i=1;i<N;i++){
		scanf("%d%d",&a,&b);
		addedge(a,b);
		addedge(b,a);
	}
}
int main(){
	freopen("haoi2015_t2.in","r",stdin);
	freopen("haoi2015_t2.out","w",stdout);
	memset(head,-1,sizeof(head));
	read();
	DFS(1);
	make_block();
	work();
	return 0;
}