您的位置:首页 > 其它

【bzoj4034】 HAOI2015 T2 树链剖分+小变形

2015-07-18 19:16 344 查看
这道题其实是个裸裸的树剖,重点在于怎样处理子树加操作,那么我们在建seq序列时,想办法把一颗子树建的连续起来就好了,那么我们就改变以往的顺序,利用dfs,先跑重链,在跑轻链,这样就把子树建到一起了,然后就非常简单了。话说,这道题跟NOI2015D1T2有什么区别么?

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 100010

using namespace std;

struct yts
{
	int l,r;
	long long data,tag;
}t[4*maxn];

int to[2*maxn],next[2*maxn],st[maxn],a[maxn];
int dep[maxn],size[maxn],dd[maxn];
int seq[maxn],mx[maxn],pos[maxn],head[maxn],fa[maxn];
int n,m,T,num,id,qwer;
bool vis[maxn];

void addedge(int x,int y)
{
	num++;to[num]=y;next[num]=st[x];st[x]=num;
}

void dfs1(int x)
{
	size[x]=1;dd[x]=0;
	for (int p=st[x];p;p=next[p])
	  if (to[p]!=fa[x])
	  {
	  	fa[to[p]]=x;dep[to[p]]=dep[x]+1;
	  	dfs1(to[p]);
	  	size[x]+=size[to[p]];
	  	if (size[to[p]]>size[dd[x]]) dd[x]=to[p];
	  }
}

void dfs2(int x,int f)
{
	head[x]=f;pos[x]=mx[x]=++id;vis[x]=1;
	if (dd[x]) dfs2(dd[x],f),mx[x]=max(mx[x],mx[dd[x]]);
	for (int p=st[x];p;p=next[p])
	  if (!vis[to[p]]) dfs2(to[p],to[p]),mx[x]=max(mx[x],mx[to[p]]);
}

void build(int i,int l,int r)
{
	t[i].l=l;t[i].r=r;
	if (l==r) {t[i].data=a[seq[l]];return;}
	int mid=(l+r)/2;
	build(i*2,l,mid);build(i*2+1,mid+1,r);
	t[i].data=t[i*2].data+t[i*2+1].data;
}

void release(int i)
{
	if (t[i].l==t[i].r) return;
	if (t[i].tag!=0)
	{
		long long d=t[i].tag;
		t[i*2].tag+=d;t[i*2+1].tag+=d;
		t[i*2].data+=d*(t[i*2].r-t[i*2].l+1);
		t[i*2+1].data+=d*(t[i*2+1].r-t[i*2+1].l+1);
		t[i].tag=0;
	}
}

void modify(int i,int l,int r,int x)
{
	if (l<=t[i].l && t[i].r<=r) {t[i].data+=(long long)(t[i].r-t[i].l+1)*x;t[i].tag+=x;return;}
	release(i);
	int mid=(t[i].l+t[i].r)/2;
	if (l<=mid) modify(i*2,l,r,x);
	if (mid<r) modify(i*2+1,l,r,x);
	t[i].data=t[i*2].data+t[i*2+1].data;
}

long long query(int i,int l,int r)
{
	if (l<=t[i].l && t[i].r<=r) return t[i].data;
	release(i);
	int mid=(t[i].l+t[i].r)/2;
	long long ans=0;
	if (l<=mid) ans+=query(i*2,l,r);
	if (mid<r) ans+=query(i*2+1,l,r);
	return ans;
}

int main()
{
	scanf("%d%d",&n,&T);
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	for (int i=1;i<n;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		addedge(x,y);
		addedge(y,x);
	}
	fa[1]=0;dep[1]=0;
	dfs1(1);
	dfs2(1,1);
	for (int i=1;i<=n;i++) seq[pos[i]]=i;
	build(1,1,n);
	while (T--)
	{
		int op;
		scanf("%d",&op);
		if (op==1)
		{
			int x,a;
			scanf("%d%d",&x,&a);
			modify(1,pos[x],pos[x],a);
		}
		if (op==2)
		{
			int x,a;
			scanf("%d%d",&x,&a);
			modify(1,pos[x],mx[x],a);
		}
		if (op==3)
		{
			int x;
			scanf("%d",&x);
			long long ans=0;
			while (dep[head[x]]>dep[1])
			{
				ans+=query(1,pos[head[x]],pos[x]);x=fa[head[x]];
			}
			ans+=query(1,pos[1],pos[x]);
			printf("%lld\n",ans);
		}
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: