P3384 【模板】树链剖分

#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
int const MXN=100005;
int n,m,R,MOD,cnt,a[MXN],hd[MXN],fa[MXN],dep[MXN],siz[MXN],b[MXN],son[MXN],id[MXN],T[MXN],tp[MXN];
int x,y;
struct Edge{
	int to,nxt;
}edge[MXN<<1];
void add(int u,int v)
{
	cnt++;
	edge[cnt].to=v;
	edge[cnt].nxt=hd[u];
	hd[u]=cnt;
}
//求深度,父节点 ,重儿子,size[] 
void dfs1(int u,int d,int f)
{
	dep[u]=d;
	siz[u]=1; 
	int mx=0;
	for(int i=hd[u];i;i=edge[i].nxt)
	{
		int v=edge[i].to;
		if(v!=f)
		{
			fa[v]=u;
			dfs1(v,d+1,u);
			if(siz[v]>mx)
			{
				mx=siz[v]; 
				son[u]=v;
			}
			siz[u]+=siz[v];	
		}
	}
}
int tot=0;
//将树映射到线性的线段树上 ,并求出top[] 
void dfs2(int u,int top)
{
	id[u]=++tot;//原树上的点在线段树上的排名 
	a[tot]=b[u];//线段树上 的权值 
	T[tot]=u;//线段树的点在原树上的编号 
	tp[u]=top;//
	if(son[u]!=0)
		dfs2(son[u],top); 
	for(int i=hd[u];i;i=edge[i].nxt)
	{
		int v=edge[i].to;
		if(v!=fa[u] && v!=son[u])
		{
//			id[v]=++tot;//少这句话 
//			a[tot]=b[v];
//			T[tot]=v;
//			tp[v]=v;//轻儿子的top就是自己		
			dfs2(v,v);	
		}
	}
}
struct Tree{
	int l,r,sum,ad;
}tre[MXN<<2];
void pushup(int rt)
{
	tre[rt].sum=(tre[rt<<1].sum+tre[rt<<1|1].sum+MOD)%MOD;
}
void build(int rt,int L,int R)
{
	tre[rt].l=L;
	tre[rt].r=R;
	if(L==R)
	{
		tre[rt].sum=a[L];
		return ;
	}
	int mid=(L+R)>>1;
	build(rt<<1,L,mid);
	build(rt<<1|1,mid+1,R);
	pushup(rt);
}
void pushdown(int rt)
{
	if(tre[rt].ad)
	{
		tre[rt<<1].ad+=tre[rt].ad;
		tre[rt<<1|1].ad+=tre[rt].ad;
		tre[rt<<1].sum+=tre[rt].ad*(tre[rt<<1].r-tre[rt<<1].l+1);
		tre[rt<<1|1].sum+=tre[rt].ad*(tre[rt<<1|1].r-tre[rt<<1|1].l+1); 
		tre[rt].ad=0;
	}
}
void update(int rt,int L,int R,int v)
{
	if(L<=tre[rt].l && R>=tre[rt].r)//少一个等于号 
	{
		tre[rt].ad+=v;
		tre[rt].sum +=v*(tre[rt].r-tre[rt].l+1);
		return;
	}
	pushdown(rt);
	int mid=(tre[rt].l+tre[rt].r)>>1;
	if(L<=mid)
		update(rt<<1,L,R,v);
	if(R>mid)
		update(rt<<1|1,L,R,v);
	pushup(rt);
}
int query(int rt,int L,int R)
{
	if(L<=tre[rt].l && R>=tre[rt].r)
		return tre[rt].sum;	
	pushdown(rt);少写 
	int mid=(tre[rt].l+tre[rt].r)>>1;
	int tmp=0;
	if(L<=mid)
		tmp=(tmp+query(rt<<1,L,R))%MOD;
	if(R>mid)
		tmp=(tmp+query(rt<<1|1,L,R))%MOD;
	return tmp;
}
int main()
{
	scanf("%d%d%d%d",&n,&m,&R,&MOD);
	for(int i=1;i<=n;i++)
		scanf("%d",&b[i]);
	for(int i=1;i<=n-1;i++)
	{
		scanf("%d%d",&x,&y);
		add(x,y);add(y,x);
	}
	dfs1(R,1,-1);
//	for(int i=1;i<=n;i++)
//		cout<dep[r]) swap(l,r);
			update(1,id[l],id[r],v);
//			cout<dep[r])swap(l,r);
			tmp=(tmp+query(1,id[l],id[r]))%MOD;
			printf("%d\n",tmp);
		}
		else if(q==3)
		{
			scanf("%d%d",&rt,&v);
			update(1,id[rt],id[rt]+siz[rt]-1,v);
//			cout<

 

你可能感兴趣的:(树剖)