[BZOJ2836] 魔法树

Description

Input

Output

Sample Input

4
0 1
1 2
2 3
4
A 1 3 1
Q 0
Q 1
Q 2

Simple Output

3
3
2

题目分析:

树链剖分+线段树裸题
咩哈哈哈我1A了

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
int n,m;
int net[201000],head[101000],to[201000];
int deep[101000],fa[101000],size[101000],top[101000],son[101000],number[101000];
int tot,cnt;
struct your
{
	int x,y;
	long long sum;
	long long add;
}a[500000];
void add(int x,int y)
{
	net[++tot]=head[x];
	to[tot]=y;
	head[x]=tot;
}
void dfs(int x,int temp)
{
	deep[x]=deep[temp]+1;
	fa[x]=temp;
	size[x]=1;
	for(int i=head[x];i;i=net[i])
		if(to[i]!=temp)
		{
			dfs(to[i],x);
			if(size[son[x]]<size[to[i]]) 
				son[x]=to[i];
			size[x]+=size[to[i]];
		}
}
void dfs2(int x,int temp)
{
	number[x]=++cnt;
	top[x]=temp;
	if(son[x]) dfs2(son[x],temp);
	for(int i=head[x];i;i=net[i])
		if(to[i]!=son[x]&&to[i]!=fa[x])
			dfs2(to[i],to[i]);
}
void build(int dx,int dy,int num)
{
	a[num].x=dx,a[num].y=dy;
	if(dx==dy) return ;
	int mid=(dx+dy)>>1;
	build(dx,mid,num<<1);
	build(mid+1,dy,num<<1|1);
}
char s[5];
void pushdown(int num)
{
	a[num<<1].add+=a[num].add;
	a[num<<1|1].add+=a[num].add;
	a[num<<1].sum+=(a[num<<1].y-a[num<<1].x+1)*a[num].add;
	a[num<<1|1].sum+=(a[num<<1|1].y-a[num<<1|1].x+1)*a[num].add;
	a[num].add=0;
}
void update(int dx,int dy,long long c,int num)
{
	if(a[num].x==dx&&a[num].y==dy)
	{
		a[num].sum=a[num].sum+(a[num].y-a[num].x+1)*c;
		a[num].add+=c;
		return;
	}
	if(a[num].add) pushdown(num);
	int mid=(a[num].x+a[num].y)>>1;
	if(dx>mid) update(dx,dy,c,num<<1|1);
	else if(dy<=mid) update(dx,dy,c,num<<1);
	else update(dx,mid,c,num<<1),update(mid+1,dy,c,num<<1|1);
	a[num].sum=a[num<<1].sum+a[num<<1|1].sum;
}
void change(int x,int y,long long c)
{
	while(top[x]!=top[y])
	{
		if(deep[top[x]]<=deep[top[y]]) swap(x,y);
		update(number[top[x]],number[x],c,1);
		x=fa[top[x]];
	}
	if(deep[x]>deep[y]) swap(x,y);
	update(number[x],number[y],c,1);
}
long long ask(int dx,int dy,int num)
{
	if(a[num].x==dx&&a[num].y==dy)
		return a[num].sum;
	if(a[num].add) pushdown(num);
	int mid=(a[num].x+a[num].y)>>1;
	if(dx>mid) return ask(dx,dy,num<<1|1);
	if(dy<=mid) return ask(dx,dy,num<<1);
	return ask(dx,mid,num<<1)+ask(mid+1,dy,num<<1|1);
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<n;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		x++,y++;
		add(x,y),add(y,x);
	}
	dfs(1,0);
	dfs2(1,1);
	build(1,n,1);
	scanf("%d",&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%s",&s[0]);
		if(s[0]=='A') 
		{
			int x,y;
			long long c;
			scanf("%d%d%lld",&x,&y,&c);
			x++;y++;
			change(x,y,c);
		}
		else
		{
			int x;
			scanf("%d",&x);
			x++;
			printf("%lld\n",ask(number[x],number[x]+size[x]-1,1));
		}
	}
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注