BZOJ 4034 [HAOI2015]树上操作

Posted zzyer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 4034 [HAOI2015]树上操作相关的知识,希望对你有一定的参考价值。

题解:树剖

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100009;
typedef long long Lint;

int n,m;

int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1];
void Addedge(int x,int y){
	nex[++cntedge]=head[x];
	to[cntedge]=y;
	head[x]=cntedge;
}

int father[maxn],siz[maxn],depth[maxn];
Lint v[maxn];
int top[maxn],hson[maxn],idx[maxn],ref[maxn];
void Dfs(int now,int fa){
	father[now]=fa;
	depth[now]=depth[fa]+1;
	siz[now]=1;
	for(int i=head[now];i;i=nex[i]){
		if(to[i]==fa)continue;
		Dfs(to[i],now);
		siz[now]+=siz[to[i]];
		if(siz[to[i]]>siz[hson[now]])hson[now]=to[i];
	}
}

int dfsclock;
void Dfs2(int now,int toppoint){
	top[now]=toppoint;
	idx[now]=++dfsclock;
	ref[dfsclock]=now;
	if(!hson[now])return;
	Dfs2(hson[now],toppoint);
	for(int i=head[now];i;i=nex[i]){
		if(to[i]==father[now])continue;
		if(to[i]==hson[now])continue;
		Dfs2(to[i],to[i]);
	}
}

struct SegmentTree{
	int l,r;
	Lint tag,sum;
}tree[maxn<<2];
void pushup(int now){
	tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;
}
void pushdown(int now){
	if(tree[now].tag){
		tree[now<<1].tag+=tree[now].tag;
		tree[now<<1].sum+=tree[now].tag*(tree[now<<1].r-tree[now<<1].l+1);
		tree[now<<1|1].tag+=tree[now].tag;
		tree[now<<1|1].sum+=tree[now].tag*(tree[now<<1|1].r-tree[now<<1|1].l+1);
		tree[now].tag=0;
	}
}
void BuildTree(int now,int l,int r){
	tree[now].l=l;tree[now].r=r;tree[now].tag=0;
	if(l==r){
		tree[now].sum=v[ref[l]];return;
	}
	int mid=(l+r)>>1;
	BuildTree(now<<1,l,mid);
	BuildTree(now<<1|1,mid+1,r);
	pushup(now);
}
void Updatasec(int now,int ll,int rr,Lint x){
//	for(int i=1;i<=1000000000;++i);
//	cout<<now<<‘ ‘<<ll<<‘ ‘<<tree[now].l<<endl;
	if(tree[now].l>=ll&&tree[now].r<=rr){
		tree[now].tag+=x;tree[now].sum+=x*(tree[now].r-tree[now].l+1);return;
	}
	pushdown(now);
	int mid=(tree[now].l+tree[now].r)>>1;
	if(ll<=mid)Updatasec(now<<1,ll,rr,x);
	if(rr>mid)Updatasec(now<<1|1,ll,rr,x);
	pushup(now);
}
Lint Querysum(int now,int ll,int rr){
	if(tree[now].l>=ll&&tree[now].r<=rr){
		return tree[now].sum;
	}
	pushdown(now);
	int mid=(tree[now].l+tree[now].r)>>1;
	Lint ret=0;
	if(ll<=mid)ret+=Querysum(now<<1,ll,rr);
	if(rr>mid)ret+=Querysum(now<<1|1,ll,rr);
	return ret;
}

Lint Getsum(int u){
	int tu=top[u];
	Lint ret=0;
	while(u){
		ret+=Querysum(1,idx[tu],idx[u]);
		u=father[tu];tu=top[u];
	}
	return ret;
}

void minit(){
	cntedge=dfsclock=0;
	memset(head,0,sizeof(head));
	memset(depth,0,sizeof(depth));
	memset(hson,0,sizeof(hson));
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)scanf("%lld",&v[i]);
	for(int i=1;i<=n-1;++i){
		int x,y;
		scanf("%d%d",&x,&y);
		Addedge(x,y);
		Addedge(y,x);
	}
	
	Dfs(1,0);
	Dfs2(1,1);
	BuildTree(1,1,n);
	
	while(m--){
		int opty,x;Lint y;
		scanf("%d%d",&opty,&x);
		if(opty<3)scanf("%lld",&y);
		if(opty==1)Updatasec(1,idx[x],idx[x],y);
		if(opty==2)Updatasec(1,idx[x],idx[x]+siz[x]-1,y);
		if(opty==3)printf("%lld\n",Getsum(x));
	}
	return 0;
}

  

以上是关于BZOJ 4034 [HAOI2015]树上操作的主要内容,如果未能解决你的问题,请参考以下文章

bzoj4034: [HAOI2015]树上操作(树剖)

bzoj 4034: [HAOI2015]树上操作 (树剖+线段树 子树操作)

bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树

BZOJ-4034: [HAOI2015]树上操作 (线段树+DFS序)

BZOJ 4034 [HAOI2015]树上操作

bzoj千题计划242:bzoj4034: [HAOI2015]树上操作