bzoj4034: [HAOI2015]T2

开始可以过样例,然而交一直WA。肉眼差错=0,拿小数据写暴力对拍果然拍出错了,改!大数据!拍!没错了。交!WA。。。又把题面看了几遍,瞄到一个绝对值什么的嗤笑一声逗我树节点的权值怎么会是负的。于是半小时后突然想到为什么不能是负的。。。就A了。。。细节细节不要太多理所当然。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
#define qwq(x) for(edge *o=head[x];o;o=o->next)
#define op() clr(head,0);pt=edges;
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
#define adde(u,v) add(u,v),add(v,u)
#define ll long long
int read(){
	int x=0;char c=getchar();bool f=true;
	while(!isdigit(c)) {
		if(c=='-') f=false; c=getchar();
	}
	while (isdigit(c)) x=x*10+c-'0',c=getchar();
	return f?x:-x;
}
const int nmax=100005;
const int inf=0x7f7f7f7f;
struct edge{
	int to;edge *next;
};
edge edges[nmax<<1],*pt,*head[nmax];
int son[nmax],size[nmax],dep[nmax],id[nmax],idx[nmax<<2],tp[nmax],fa[nmax],w[nmax],lft[nmax],rht[nmax],n;
ll sum[nmax<<2],col[nmax<<2];
void add(int u,int v){
	pt->to=v;pt->next=head[u];head[u]=pt++;
}
void dfs(int x,int father){
	size[x]=1;
	qwq(x){
		int to=o->to;
		if(to==father) continue;
		dep[to]=dep[x]+1;fa[to]=x;dfs(to,x);
		size[x]+=size[to];
		if(!son[x]||size[to]>size[son[x]]) son[x]=to;
	}
}
void Dfs(int x,int top){
	id[x]=++id[0];idx[id[0]]=x;lft[x]=id[0];tp[x]=top;
	if(son[x]) Dfs(son[x],top);
	qwq(x) if(!id[o->to]) Dfs(o->to,o->to);
	rht[x]=id[0];
}
void build(int l,int r,int x){
	if(l==r) {
		sum[x]=w[idx[l]];return ;
	}
	int m=(l+r)>>1;build(lson);build(rson);sum[x]=sum[x<<1]+sum[x<<1|1];
}
void pushdown(int x,int tmp){
	if(col[x]){
		sum[x<<1]+=col[x]*(tmp-(tmp>>1));sum[x<<1|1]+=col[x]*(tmp>>1);
		col[x<<1]+=col[x];col[x<<1|1]+=col[x];col[x]=0;
	}
}
void update(int tl,int tr,int add,int l,int r,int x){
	if(tl<=l&&tr>=r){
		sum[x]+=(ll)add*(r-l+1);col[x]+=add;return ;
	}
	pushdown(x,r-l+1);
	int m=(l+r)>>1;
	if(tl<=m) update(tl,tr,add,lson);
	if(tr>m) update(tl,tr,add,rson);
	sum[x]=sum[x<<1]+sum[x<<1|1];
}
ll query(int tl,int tr,int l,int r,int x){
	if(tl<=l&&tr>=r) return sum[x];
	pushdown(x,r-l+1);
	int m=(l+r)>>1;ll ans=0;
	if(tl<=m) ans+=query(tl,tr,lson);
	if(tr>m) ans+=query(tl,tr,rson);
	return ans;
}
ll qsum(int a,int b){
	ll ans=0;
	while(tp[a]!=tp[b]) {
		ans+=query(id[tp[b]],id[b],1,n,1);
		b=fa[tp[b]];
		//printf("%d ",tp[b]);
	}
	//printf("
");
	ans+=query(id[a],id[b],1,n,1);
	return ans;
}
int main(){
	/*freopen("data.out","r",stdin);
	freopen("4034.out","w",stdout);*/
	op();
	n=read();int m=read(),u,v,d;
	rep(i,n) w[i]=read();
	rep(i,n-1) u=read(),v=read(),adde(u,v);
	clr(fa,0);clr(son,0);dep[1]=0;
	clr(id,0);
	dfs(1,-1);
	//rep(i,n) printf("%d:%d %d %d %d
",i,fa[i],size[i],son[i],dep[i]);
	Dfs(1,1);
	//rep(i,n) printf("%d ",id[i]);printf("
");
	//rep(i,n) printf("%d ",tp[i]);
	build(1,n,1);
	rep(i,m){
		u=read();
		if(u==1) v=read(),d=read(),update(id[v],id[v],d,1,n,1);
		else if(u==2) v=read(),d=read(),update(lft[v],rht[v],d,1,n,1);
		else v=read(),printf("%lld
",qsum(1,v));
	}
	return 0;
}

 

4034: [HAOI2015]T2

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 2654  Solved: 835
[Submit][Status][Discuss]

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

[Submit][Status][Discuss]
原文地址:https://www.cnblogs.com/fighting-to-the-end/p/5663382.html