天天看点

bzoj 2836: 魔法树(树链剖分)

2836: 魔法树

Time Limit: 10 Sec   Memory Limit: 128 MB

Submit: 247   Solved: 96

[ Submit][ Status][ Discuss]

Description

bzoj 2836: 魔法树(树链剖分)

Input

bzoj 2836: 魔法树(树链剖分)

Output

bzoj 2836: 魔法树(树链剖分)

Sample Input

4

0 1

1 2

2 3

4

Add 1 3 1

Query 0

Query 1

Query 2

Sample Output

3

3

2

HINT

Source

[ Submit][ Status][ Discuss]

题解:dfs序+树链剖分

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 200003
#define LL long long
using namespace std;
int n,m,t,tot,sz;
LL tr[N*4],delta[N*4];
int point[N],next[N],v[N],belong[N],size[N],son[N],fa[N],deep[N];
int pos[N],l[N],r[N];
void add(int x,int y)
{
	tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y;
	tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void dfs(int x,int f)
{
	size[x]=1;
	for (int i=point[x];i;i=next[i])
	 if (v[i]!=f)
	 {
	 	deep[v[i]]=deep[x]+1;
	 	dfs(v[i],x);
	 	fa[v[i]]=x;
	 	size[x]+=size[v[i]];
	 	if (size[v[i]]>size[son[x]])
	 	 son[x]=v[i];
	 }
}
void build(int k,int chain)
{
	belong[k]=chain; pos[k]=++sz;
	l[k]=sz; r[k]=sz;
	if (!son[k]) return;
	build(son[k],chain);
	for (int i=point[k];i;i=next[i])
	 if (v[i]!=fa[k]&&v[i]!=son[k])
	  build(v[i],v[i]);
	r[k]=sz;
}
void pushdown(int now,int l,int r)
{
	if (!delta[now]) return;
	delta[now<<1]+=delta[now];
	delta[now<<1|1]+=delta[now];
	int mid=(l+r)/2;
	tr[now<<1]+=(LL)(mid-l+1)*delta[now];
	tr[now<<1|1]+=(LL)(r-mid)*delta[now];
	delta[now]=0;
}
LL query(int now,int l,int r,int ll,int rr)
{
	if (l>=ll&&r<=rr) return tr[now];
	pushdown(now,l,r);
	int mid=(l+r)/2;
	LL ans=0;
	if (ll<=mid)  ans+=query(now<<1,l,mid,ll,rr);
	if (rr>mid)  ans+=query(now<<1|1,mid+1,r,ll,rr);
	return ans; 
}
void change(int now,int l,int r,int ll,int rr,LL v)
{
	if (l>=ll&&r<=rr){
		tr[now]+=(LL)v*(r-l+1);
		delta[now]+=v;
		return;
	}
	pushdown(now,l,r);
	int mid=(l+r)/2;
	if (ll<=mid) change(now<<1,l,mid,ll,rr,v);
	if (rr>mid) change(now<<1|1,mid+1,r,ll,rr,v);
	tr[now]=tr[now<<1]+tr[now<<1|1];
}
void solve(int x,int y,LL v)
{
	while (belong[x]!=belong[y])
	 {
	 	if (deep[belong[x]]<deep[belong[y]]) swap(x,y);
	 	change(1,1,n,pos[belong[x]],pos[x],v);
	 	x=fa[belong[x]];
	 }
	if (deep[x]>deep[y]) swap(x,y);
	change(1,1,n,pos[x],pos[y],v);
}
int main() 
{
	freopen("a.in","r",stdin);
	scanf("%d",&n);
	for (int i=1;i<n;i++) 
	 {
	 	int x,y; scanf("%d%d",&x,&y); x++; y++;
	 	add(x,y);
	 }
	deep[1]=1;
	dfs(1,0);
	build(1,1);
	scanf("%d",&t);
	for (int i=1;i<=t;i++)
	 {
	 	char s[10]; scanf("%s",s);
	 	if (s[0]=='A'){
	 	   int x,y; LL z; scanf("%d%d%I64d",&x,&y,&z);
	 	   x++; y++;
	 	   solve(x,y,z);
	    }
	    else{
	       int x; scanf("%d",&x); x++;
		   printf("%I64d\n",query(1,1,n,l[x],r[x]));	
	    }
	 }
}
           

继续阅读