【洛谷3384】【模板】树链剖分

题目自己到洛谷上去看

题解

树链剖分模板题,以后再写详细的树链剖分(让我多做几道题)
先放代码,以后再补充详细的解释(留个坑)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAX 120000
#define MAXL MAX+MAX
#define lson (now<<1)
#define rson ((now<<1)|1)
inline int read()
{
	  register int x=0,t=1;
	  register char ch=getchar();
	  while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	  if(ch=='-'){t=-1;ch=getchar();}
	  while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
	  return x*t;
}
struct Line
{
	int v,next,w;
}e[MAXL];
int h[MAX],cnt=1;
int dep[MAX],hson[MAX],size[MAX],f[MAX],VV[MAX],V[MAX];
int top[MAX],idb[MAX],ide[MAX],tot,N,M,P,R,line[MAX];
struct Node
{
	int val,lazy;
}c1[MAX*8];
inline void Add(int u,int v)
{
	e[cnt]=(Line){v,h[u]};
	h[u]=cnt++; 
}
void DFS1(int u,int ff)
{
	dep[u]=dep[ff]+1;//求深度
	size[u]=1;//子树大小
	hson[u]=0;//重儿子
	f[u]=ff;//父亲
	int v;
	for(int i=h[u];i;i=e[i].next)
	{
		v=e[i].v;
		if(v==ff)continue;
		DFS1(v,u);
		size[u]+=size[v]; 
		if(size[v]>size[hson[u]])hson[u]=v;//求出重儿子 
	}
}
void DFS2(int u,int ff)
{
	top[u]=ff;//重链顶端 
	idb[u]=++tot;//DFS序
	line[tot]=u;
	if(hson[u])DFS2(hson[u],ff);//强制先走重链
	for(int i=h[u];i;i=e[i].next)
	{
		int v=e[i].v;
		if(v==f[u]||v==hson[u])continue;
		DFS2(v,v);//走轻链
	}
	ide[u]=tot;//子树结束位置 
}
void pushdown1(int now,int l,int r)
{
	c1[now].val=(c1[now].val+1LL*(r-l+1)*c1[now].lazy)%P;
	c1[lson].lazy=(c1[lson].lazy+c1[now].lazy)%P;
	c1[rson].lazy=(c1[rson].lazy+c1[now].lazy)%P;
	c1[now].lazy=0;
}
void build1(int now,int l,int r)
{
	if(l==r){c1[now].val=V[line[l]];return;}
	int mid=(l+r)>>1;
	build1(lson,l,mid);build1(rson,mid+1,r);
	c1[now].val=(c1[lson].val+c1[rson].val)%P;
}
void update1(int now,int l,int r,int al,int ar,int w)
{
	if(al==l&&ar==r){c1[now].lazy+=w;return;}
	int mid=(l+r)>>1;
	(c1[now].val+=1LL*(ar-al+1)*w)%=P;
	if(ar<=mid)update1(lson,l,mid,al,ar,w);
	else if(al>mid)update1(rson,mid+1,r,al,ar,w);
	else {update1(lson,l,mid,al,mid,w);update1(rson,mid+1,r,mid+1,ar,w);}
}
int Query1(int now,int l,int r,int al,int ar)
{
	pushdown1(now,l,r);
	if(al==l&&ar==r)return c1[now].val%P;
	int mid=(l+r)>>1;
	if(ar<=mid)return Query1(lson,l,mid,al,ar);
	if(al>mid)return Query1(rson,mid+1,r,al,ar);
	return (Query1(lson,l,mid,al,mid)+Query1(rson,mid+1,r,mid+1,ar))%P;
}
void Change(int u,int v,int w)
{
	int tp1=top[u],tp2=top[v];
	while(tp1!=tp2)
	{
		if(dep[tp1]<dep[tp2])
		{
			swap(tp1,tp2);
			swap(u,v);
		}
		update1(1,1,N,idb[tp1],idb[u],w);
		u=f[tp1];
		tp1=top[u];
	}
	if(dep[u]<dep[v])swap(u,v);
	update1(1,1,N,idb[v],idb[u],w);
}
int Ask(int u,int v)
{
	int tp1=top[u],tp2=top[v],re=0;
	while(tp1!=tp2)
	{
		if(dep[tp1]<dep[tp2])
		{
			swap(tp1,tp2);
			swap(u,v);
		}
		re=(re+Query1(1,1,N,idb[tp1],idb[u]))%P;
		u=f[tp1];
		tp1=top[u];
	}
	if(dep[u]<dep[v])swap(u,v);
	return (re+Query1(1,1,N,idb[v],idb[u]))%P;
}
int main()
{
	N=read();M=read();R=read();P=read();
	for(int i=1;i<=N;++i)V[i]=read();
	for(int i=1;i<N;++i)
	{
		int u=read(),v=read();
		Add(u,v);Add(v,u);
	}
	DFS1(R,0);DFS2(R,R);
	build1(1,1,N);
	for(int i=1;i<=M;++i)
	{
		int kk=read();
		if(kk==1)
		{
			int a=read(),b=read(),c=read();
			Change(a,b,c);
		}
		if(kk==2)
		{
			int a=read(),b=read();
			printf("%d\n",Ask(a,b)%P);
		}
		if(kk==3)
		{
			int a=read(),b=read();
			update1(1,1,N,idb[a],ide[a],b);
		}
		if(kk==4)
		{
			int a=read();
			printf("%d\n",Query1(1,1,N,idb[a],ide[a])%P);
		}
	}
}



posted @ 2017-08-24 20:18  小蒟蒻yyb  阅读(388)  评论(6编辑  收藏  举报