【HAOI2015】树上操作(树链剖分模板)

原题见洛谷。

既然是模板,没什么可分析的,只是有几个小地方:

1,两种修改操作可以合并为一个,只需写区间修改,然后对于点修改,把区间两端都设为点的DFS序即可。

2,询问时,可以不用改模板,直接当作u=1,另一个v输入。

3,没事就pushup一下,至少不会错。

4,要用long long。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN=100005;
int lc[MAXN*2],rc[MAXN*2];
int last[MAXN],fa[MAXN],size[MAXN],dep[MAXN],top_node[MAXN],big_son[MAXN],dfs_pos[MAXN],a[MAXN],b[MAXN];
int N,M,np=0,np2=0,rt=0,dfs_clock=0;
LL sum[MAXN*2],lazy[MAXN*2];
struct edge{int to,pre;}E[MAXN*2];

char c;int flag;
void scan(int &x)
{
	flag=1;
	for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
	if(c=='-') flag=-1,c=getchar();
	for(x=0;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
	x*=flag;
}

char num[50];int ct;
void print(LL x)
{
	ct=0;
	if(x<0) putchar('-'),x=-x;
	if(!x) num[ct++]='0';
	while(x) num[ct++]=x%10+'0',x/=10;
	while(ct--) putchar(num[ct]);
	putchar('\n');
}
//------------------------------------
void addedge(int u,int v)
{
	E[++np2]=(edge){v,last[u]};
	last[u]=np2;
}

void DFS1(int i,int f,int d)
{
	dep[i]=d; fa[i]=f; size[i]=1;
	for(int p=last[i];p;p=E[p].pre)
	{
		int j=E[p].to;
		if(j==f) continue;
		DFS1(j,i,d+1); size[i]+=size[j];
		if(size[j]>size[big_son[i]]) big_son[i]=j;
	}
}

void DFS2(int i,int top)
{
	dfs_pos[i]=++dfs_clock;
	top_node[i]=top; b[dfs_clock]=a[i];
	if(!big_son[i]) return;
	DFS2(big_son[i],top);
	for(int p=last[i];p;p=E[p].pre)
	{
		int j=E[p].to;
		if(j==fa[i]||j==big_son[i]) continue;
		DFS2(j,j);
	}
}
//-------------------------------------
void pushup(int now) {sum[now]=sum[lc[now]]+sum[rc[now]];}

void build(int &now,int L,int R)
{
	if(!now) now=++np;
	if(L==R)
	{
		sum[now]=(LL)b[L];
		return;
	}
	int mid=(L+R)/2;
	build(lc[now],L,mid);
	build(rc[now],mid+1,R);
	pushup(now);
}

void f(int now,int L,int R,LL d)
{
	lazy[now]+=d;
	sum[now]+=(LL)(R-L+1)*d;
}

void pushdown(int now,int L,int R)
{
	if(!lazy[now]) return;
	int mid=(L+R)/2;
	f(lc[now],L,mid,lazy[now]);
	f(rc[now],mid+1,R,lazy[now]);
	lazy[now]=0;
}

void update(int now,int L,int R,int i,int j,LL d)
{
	if(i<=L&&R<=j)
	{
		lazy[now]+=d;
		sum[now]+=(LL)(R-L+1)*d;
		return;
	}
	pushdown(now,L,R);
	int mid=(L+R)/2;
	if(i<=mid) update(lc[now],L,mid,i,j,d);
	if(mid<j) update(rc[now],mid+1,R,i,j,d);
	pushup(now);
}

LL ques(int now,int L,int R,int i,int j)
{
	if(i<=L&&R<=j) return sum[now];
	pushdown(now,L,R);
	int mid=(L+R)/2; LL ans=0;
	if(i<=mid) ans+=ques(lc[now],L,mid,i,j);
	if(mid<j) ans+=ques(rc[now],mid+1,R,i,j);
 	pushup(now); return ans;
}

LL ques_range(int u,int v)
{
	LL ans=0;
	while(top_node[u]!=top_node[v])
	{
		if(dep[top_node[u]]<dep[top_node[v]]) swap(u,v);
		ans+=ques(rt,1,N,dfs_pos[top_node[u]],dfs_pos[u]);
		u=fa[top_node[u]];
	}
	if(dep[u]>dep[v]) swap(u,v);
	return ans+ques(rt,1,N,dfs_pos[u],dfs_pos[v]);
}

int main()
{
	int i,u,v,w,op;
	scan(N);scan(M);
	for(i=1;i<=N;i++) scan(a[i]);
	for(i=1;i<N;i++)
	{
		scan(u);scan(v);
		addedge(u,v);
		addedge(v,u);
	}
	DFS1(1,0,1); DFS2(1,1); build(rt,1,N);
	while(M--)
	{
		scan(op);
		if(op==1)
		{
			scan(u);scan(w);
			update(rt,1,N,dfs_pos[u],dfs_pos[u],(LL)w);
		}
		else if(op==2)
		{
			scan(u);scan(w);
			update(rt,1,N,dfs_pos[u],dfs_pos[u]+size[u]-1,(LL)w);
		}
		else
		{
			scan(u);
			print(ques_range(1,u));
		}
	}
	return 0;
}

 

猜你喜欢

转载自blog.csdn.net/WWWengine/article/details/81661926