P3384-[模板]树链剖分

版权声明:原创,未经作者允许禁止转载 https://blog.csdn.net/Mr_wuyongcong/article/details/86768569

正题


题目大意

要求支持路径加和求和,子树加和求和


解题思路

树剖不解释


c o d e code

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=200000;
int tot,cnt,n,m,s,p,ls[N],pw[N],id[N];
int siz[N],dep[N],f[N],son[N],seg[N],top[N];
struct treenode{
	int l,r,lazy,val;
};
struct LineTree{
	treenode t[N*2];
	void build(int x,int l,int r)
	{
    	t[x].l=l;t[x].r=r;
    	if(l==r)
    	{
        	t[x].val=pw[id[l]]%p;
        	return;
        }
    	int mid=(l+r)>>1;
    	build(x*2,l,mid);
    	build(x*2+1,mid+1,r);
    	t[x].val=(t[x*2].val+t[x*2+1].val)%p;
	}
	void downdata(int x)
	{
    	if(t[x].lazy)
    	{
        	(t[x*2].lazy+=t[x].lazy)%=p;
        	(t[x*2].val+=t[x].lazy*(t[x*2].r-t[x*2].l+1))%=p;
        	(t[x*2+1].lazy+=t[x].lazy)%=p;
        	(t[x*2+1].val+=t[x].lazy*(t[x*2+1].r-t[x*2+1].l+1))%=p;
        	t[x].lazy=0;
    	}
	}
	void change(int x,int l,int r,int num)
	{
    	if(t[x].l==l&&t[x].r==r)
    	{
        	(t[x].val+=num*(t[x].r-t[x].l+1))%=p;
        	(t[x].lazy+=num)%=p;
        	return;
    	}
    	downdata(x);
    	int mid=(t[x].l+t[x].r)>>1;
    	if(r<=mid) change(x*2,l,r,num);
    	else if(l>mid) change(x*2+1,l,r,num);
    	else change(x*2,l,mid,num),change(x*2+1,mid+1,r,num);
    	t[x].val=(t[x*2].val+t[x*2+1].val)%p;
	}
	int find(int x,int l,int r)
	{
    	if(t[x].l==l&&t[x].r==r)
        	return t[x].val;
    	downdata(x);
    	int mid=(t[x].l+t[x].r)>>1;
    	if(r<=mid) return find(x*2,l,r);
    	else if(l>mid) return find(x*2+1,l,r);
    	else return (find(x*2,l,mid)+find(x*2+1,mid+1,r))%p;    
	}
}LT;
struct edge_node{
	int to,next;
}a[N*2];
void addl(int x,int y)
{
	a[++tot].to=y;
	a[tot].next=ls[x];
	ls[x]=tot;
}
void dfs1(int x,int fa)
{
	siz[x]=1;
	for(int i=ls[x];i;i=a[i].next)
	{
		int y=a[i].to;
		if(y==fa) continue;
		dep[y]=dep[x]+1;
		f[y]=x;
		dfs1(y,x);
		siz[x]+=siz[y];
		if(siz[y]>siz[son[x]])
		  son[x]=y;
	}
}
void dfs2(int x,int fa)
{
	seg[x]=++cnt;
	id[cnt]=x;
	if(son[x])
	{
		top[son[x]]=top[x];
		dfs2(son[x],x);
	}
	for(int i=ls[x];i;i=a[i].next){
		int y=a[i].to;
		if(y==fa||y==son[x]) continue;
		top[y]=y;dfs2(y,x);
	}
}
void path_change(int x,int y,int z)
{
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		LT.change(1,seg[top[x]],seg[x],z);
		x=f[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	LT.change(1,seg[x],seg[y],z);
	return;
}
int path_ask(int x,int y)
{
	int ans=0;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		(ans+=LT.find(1,seg[top[x]],seg[x]))%=p;
		x=f[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	(ans+=LT.find(1,seg[x],seg[y]))%=p;
	return ans;
}
int main()
{
	scanf("%d%d%d%d",&n,&m,&s,&p);
	for(int i=1;i<=n;i++)
	  scanf("%d",&pw[i]);
	for(int i=1;i<n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		addl(x,y);addl(y,x);
	}
	dfs1(s,0);
	top[s]=s;dfs2(s,0);
	LT.build(1,1,n);
	for(int i=1;i<=m;i++){
		int t,x,y,z;
		scanf("%d%d",&t,&x);
		if(t==1){
			scanf("%d%d",&y,&z);
			path_change(x,y,z);
		}
		if(t==2){
			scanf("%d",&y);
			printf("%d\n",path_ask(x,y));
		}
		if(t==3){
			scanf("%d",&z);
			LT.change(1,seg[x],seg[x]+siz[x]-1,z);
		}
		if(t==4){
			printf("%d\n",LT.find(1,seg[x],seg[x]+siz[x]-1));
		}
	}
}

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/86768569