洛谷 3833 SHOI 2012 魔法树

【题解】

  树链剖分模板题。。

#include<cstdio>
#include<algorithm>
#include<queue>
#define N 500010
#define rg register
#define ls (u<<1)
#define rs (u<<1|1)
#define mid ((a[u].l+a[u].r)>>1)
#define len(x) (a[x].r-a[x].l+1)
using namespace std;
int n,m,rt,num,x,y,z,fa[N],dfn[N],dep[N],size[N],heavy[N],top[N];
vector<int>son[N];
struct tree{
	int l,r;
	long long sum,del;
}a[N];
inline int read(){
	int k=0,f=1; char c=getchar();
	while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
	while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
	return k*f;
}
inline void pushup(int u){
	a[u].sum=a[ls].sum+a[rs].sum;
}
inline void pushdown(int u){
	if(!a[u].del) return; long long d=a[u].del; a[u].del=0;
	a[ls].del+=d; a[ls].sum+=d*len(ls);
	a[rs].del+=d; a[rs].sum+=d*len(rs);
}
void build(int u,int l,int r){
	a[u].l=l; a[u].r=r; a[u].sum=a[u].del=0;
	if(l<r) build(ls,l,mid),build(rs,mid+1,r);
}
void update(int u,int l,int r,long long d){
	if(l<=a[u].l&&a[u].r<=r){
		a[u].del+=d; a[u].sum+=d*len(u); return;
	}
	pushdown(u);
	if(l<=mid) update(ls,l,r,d);
	if(r>mid) update(rs,l,r,d);
	pushup(u);
}
long long query(int u,int l,int r){
	if(l<=a[u].l&&a[u].r<=r) return a[u].sum;
	pushdown(u); long long ret=0;
	if(l<=mid) ret+=query(ls,l,r);
	if(r>mid) ret+=query(rs,l,r);
	return ret;
}
void dfs1(int x){
	size[x]=1; dep[x]=dep[fa[x]]+1;
	for(rg int i=0;i<son[x].size();i++){
		dfs1(son[x][i]);
		size[x]+=size[son[x][i]];
		if(size[son[x][i]]>size[heavy[x]]) heavy[x]=son[x][i];
	}
}
void dfs2(int x,int tp){
	top[x]=tp; dfn[x]=++num;
	if(heavy[x]) dfs2(heavy[x],tp);
	for(rg int i=0;i<son[x].size();i++)
		if(son[x][i]!=heavy[x]) dfs2(son[x][i],son[x][i]);
}
int main(){
	n=read(); 
	for(rg int i=1;i<n;i++){
		int x=read(),y=read();
		fa[y]=x; son[x].push_back(y);
		if(x==0) rt=x;
	}
	dfs1(rt); dfs2(rt,rt); 
//	for(rg int i=0;i<=n;i++) printf("%d ",size[i]); puts("");
//	for(rg int i=0;i<=n;i++) printf("%d ",dfn[i]); puts("");
	build(1,1,n);
	m=read();
	while(m--){
		char c=getchar();
		while(c!='A'&&c!='Q')c=getchar();
		if(c=='A'){
			x=read(),y=read(),z=read();
			while(top[x]!=top[y]){
				if(dep[top[x]]<dep[top[y]]) swap(x,y);
				update(1,dfn[top[x]],dfn[x],z);
				x=fa[top[x]];
			}
			if(dep[x]>dep[y]) swap(x,y);
			update(1,dfn[x],dfn[y],z);
		}
		else x=read(),printf("%lld
",query(1,dfn[x],dfn[x]+size[x]-1));
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/DriverLao/p/8612034.html