洛谷P3833 [SHOI2012]魔法树

题目

https://www.luogu.com.cn/problem/P3833

思路

思路?义眼丁真,鉴定为:纯纯的板题。

但是我是傻逼,符号写反WA了两发,得赶紧找点数据结构题练练手。

代码

点击查看代码
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define maxn 100010
#define ll long long
using namespace std;
int fst[maxn],nxt[maxn],to[maxn],cnt=0,fa[maxn];
int son[maxn],sz[maxn],deep[maxn],top[maxn],dfn[maxn],idx=0;
int l[maxn<<2],r[maxn<<2];
ll sum[maxn<<2],tag[maxn<<2];
void addedge(int x,int y){
	to[++cnt]=y;
	nxt[cnt]=fst[x];
	fst[x]=cnt;
}
void dfs1(int x){
	sz[x]++;
	deep[x]=deep[fa[x]]+1;
	for(int i=fst[x];i;i=nxt[i]){
		if(to[i]==fa[x]) continue;
		dfs1(to[i]);
		sz[x]+=sz[to[i]];
		if(sz[to[i]]>sz[son[x]]) son[x]=to[i];
	}
}
void dfs2(int x){
	dfn[x]=++idx;
	if(son[fa[x]]==x) top[x]=top[fa[x]];
	else top[x]=x;
	if(son[x]) dfs2(son[x]);
	for(int i=fst[x];i;i=nxt[i]){
		if(to[i]==fa[x]||to[i]==son[x]) continue;
		dfs2(to[i]);
	}
}
void build(int x,int left,int right){
	l[x]=left,r[x]=right;
	if(left==right) return;
	int mid=left+right>>1;
	build(x<<1,left,mid);
	build(x<<1|1,mid+1,right);
}
void update(int x){
	sum[x]=sum[x<<1]+sum[x<<1|1];
}
void pushdown(int x){
	if(tag[x]){
		tag[x<<1]+=tag[x];
		tag[x<<1|1]+=tag[x];
		sum[x<<1]+=tag[x]*(r[x<<1]-l[x<<1]+1);
		sum[x<<1|1]+=tag[x]*(r[x<<1|1]-l[x<<1|1]+1);//sum[x>>1|1]+=tag[x]*(r[x<<1|1]-l[x<<1|1]+1);woshishabi
		tag[x]=0;
	}
}
void modify(int x,int left,int right,ll k){
	if(l[x]>=left&&r[x]<=right){
		sum[x]+=k*(r[x]-l[x]+1);
		tag[x]+=k;
		return;
	}
	pushdown(x);
	int mid=l[x]+r[x]>>1;
	if(left<=mid) modify(x<<1,left,right,k);
	if(right>mid) modify(x<<1|1,left,right,k);
	update(x);
}
void change(int x,int y,int d){
	while(top[x]!=top[y]){
		if(deep[top[x]]>deep[top[y]]) swap(x,y);
		modify(1,dfn[top[y]],dfn[y],d);
		y=fa[top[y]];
	}
	if(deep[x]>deep[y]) swap(x,y);
	modify(1,dfn[x],dfn[y],d);
}
ll query(int x,int left,int right){
	ll r1=0,r2=0;
	if(l[x]>=left&&r[x]<=right) return sum[x];
	int mid=l[x]+r[x]>>1;
	pushdown(x);
	if(left<=mid) r1=query(x<<1,left,right);
	if(right>mid) r2=query(x<<1|1,left,right);
	update(x);
	return r1+r2;
}
int main(){
	int i,j,n,m,x,y,d;
	ll ans;
	char op[3];
	scanf("%d",&n);
	for(i=2;i<=n;++i){
		scanf("%d%d",&x,&y);
		fa[y+1]=x+1;
		addedge(x+1,y+1);
	}
	dfs1(1);dfs2(1);
	build(1,1,n);
	scanf("%d",&m);
	for(i=1;i<=m;++i){
		scanf("%s",op);
		if(op[0]=='A'){
			scanf("%d%d%d",&x,&y,&d);
			change(x+1,y+1,d);
		}
		else{
			scanf("%d",&x);
			ans=query(1,dfn[x+1],dfn[x+1]+sz[x+1]-1);
			printf("%lld\n",ans);
		}
	}
	// system("pause");
	return 0;
}
posted @ 2022-05-25 12:32  文艺平衡树  阅读(22)  评论(0编辑  收藏  举报