【DFS序】【线段树】bzoj4034 [HAOI2015]T2

分开维护树的入栈序和出栈序,用两棵线段树。回答时就是用一颗的减去另一棵的。

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
#define N 100001
ll sumv[2][N<<2],delta[2][N<<2];
void pushdown(int o,int rt,int sz)
{
	if(delta[o][rt])
	  {
	  	delta[o][rt<<1]+=delta[o][rt];
	  	delta[o][rt<<1|1]+=delta[o][rt];
	  	sumv[o][rt<<1]+=delta[o][rt]*(ll)(sz-(sz>>1));
	  	sumv[o][rt<<1|1]+=delta[o][rt]*(ll)(sz>>1);
	  	delta[o][rt]=0;
	  }
}
void Update(int o,int ql,int qr,int v,int rt,int l,int r)
{
	if(ql<=l&&r<=qr)
	  {
	  	delta[o][rt]+=(ll)v;
	  	sumv[o][rt]+=(ll)v*(ll)(r-l+1);
	  	return;
	  }
	int m=(l+r>>1);
	pushdown(o,rt,r-l+1);
	if(ql<=m) Update(o,ql,qr,v,rt<<1,l,m);
	if(m<qr) Update(o,ql,qr,v,rt<<1|1,m+1,r);
	sumv[o][rt]=sumv[o][rt<<1]+sumv[o][rt<<1|1];
}
ll Query(int o,int qr,int rt,int l,int r)
{
	if(r<=qr) return sumv[o][rt];
	int m=(l+r>>1); ll res=0;
	pushdown(o,rt,r-l+1);
	res+=Query(o,qr,rt<<1,l,m);
	if(m<qr) res+=Query(o,qr,rt<<1|1,m+1,r);
	return res;
}
int n,m,a[N];
int e,v[N<<1],first[N],next[N<<1];
void AddEdge(int U,int V)
{
	v[++e]=V;
	next[e]=first[U];
	first[U]=e;
}
int Ls[N],Rs[N],oLs[N],oRs[N],xu[N<<1];
int tot,to2,to3;
void dfs(int U,int Fa)
{
	Ls[U]=++tot;
	xu[++to3]=U;
	for(int i=first[U];i;i=next[i])
	  if(v[i]!=Fa)
	    dfs(v[i],U);
	Rs[U]=tot;
	xu[++to3]=U;
	oRs[U]=oLs[U]=++to2;
}
void df2(int U,int Fa)
{
	for(int i=first[U];i;i=next[i])
	  if(v[i]!=Fa)
	    {
	      df2(v[i],U);
	      oLs[U]=min(oLs[U],oLs[v[i]]);
	    }
}
bool hav[N];
int Map[N];
int main()
{
	int x,y,op;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
	  scanf("%d",&a[i]);
	for(int i=1;i<n;++i)
	  {
	  	scanf("%d%d",&x,&y);
	  	AddEdge(x,y);
	  	AddEdge(y,x);
	  }
	dfs(1,0);
	df2(1,0);
	int last=0;
	for(int i=1;i<=to3;++i)
	  if(!hav[xu[i]])
	  	{
	  	  Map[xu[i]]=last;
	  	  hav[xu[i]]=1;
	  	}
	  else
	    last=xu[i];
	for(int i=1;i<=n;++i)
	  {
	  	Update(0,Ls[i],Ls[i],a[i],1,1,n);
	  	Update(1,oRs[i],oRs[i],a[i],1,1,n);
	  }
	for(;m;--m)
	  {
	  	scanf("%d%d",&op,&x);
	  	if(op==1)
	  	  {
	  	  	scanf("%d",&y);
	  	  	Update(0,Ls[x],Ls[x],y,1,1,n);
	  		Update(1,oRs[x],oRs[x],y,1,1,n);
	  	  }
	  	else if(op==2)
	  	  {
	  	  	scanf("%d",&y);
	  	  	Update(0,Ls[x],Rs[x],y,1,1,n);
	  		Update(1,oLs[x],oRs[x],y,1,1,n);
	  	  }
	  	else
	  	  printf("%I64d\n",Query(0,Ls[x],1,1,n)-((!Map[x])?0:Query(1,oRs[Map[x]],1,1,n)));
	  }
	return 0;
}
posted @ 2015-05-15 09:46  AutSky_JadeK  阅读(155)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト