MnZn求助
查看原帖
MnZn求助
335136
LordLaffey楼主2021/7/22 16:42
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int SIZE=1e5+10;
int ls(int i){return i<<1;}
int rs(int i){return i<<1|1;}
int _max(int x,int y){return x>y?x:y;}
struct Edge{
	int v,next;
}edge[2*SIZE];
int head[SIZE],cnt=1;
int data[SIZE],ndata[SIZE];
int fa[SIZE],deep[SIZE],size[SIZE],hson[SIZE];
int top[SIZE],dfn[SIZE],tot,p;

struct LT{
	
	int l,r;
	int sum,lz;
	
}line_tree[SIZE*4+10];

void build(int l,int r,int i){
	
	line_tree[i].l=l,line_tree[i].r=r;
	if(l==r){line_tree[i].sum=ndata[l];return ;}
	int mid=(l+r)>>1;
	build(l,mid,ls(i));
	build(mid+1,r,rs(i));
	line_tree[i].sum=(line_tree[ls(i)].sum+line_tree[rs(i)].sum)%p;
	
}

void lztage(int i){
	
	line_tree[ls(i)].sum+=(line_tree[ls(i)].r-line_tree[ls(i)].l+1)*line_tree[i].lz;
	line_tree[rs(i)].sum+=(line_tree[rs(i)].r-line_tree[rs(i)].r+1)*line_tree[i].lz;
	line_tree[ls(i)].sum%=p;line_tree[rs(i)].sum%=p;
	line_tree[ls(i)].lz+=line_tree[i].lz;line_tree[rs(i)].lz+=line_tree[i].lz;
	line_tree[i].lz=0;
	
}

int search(int l,int r,int i){
	
	if(line_tree[i].l>=l&&line_tree[i].r<=r) return line_tree[i].sum%p;
	lztage(i);
	int sum=0;
	if(line_tree[ls(i)].r>=l) sum+=search(l,r,ls(i));
	if(line_tree[rs(i)].l<=r) sum+=search(l,r,rs(i));
	return sum%p;
	
}

void add(int l,int r,int i,int k){
	
	if(line_tree[i].l>=l&&line_tree[i].r<=r)
	{
		line_tree[i].sum+=(line_tree[i].r-line_tree[i].l+1)*k;
		line_tree[i].sum%=p;
		line_tree[i].lz+=k;
		return ;
	}
	lztage(i);
	if(line_tree[ls(i)].r>=l) add(l,r,ls(i),k);
	if(line_tree[rs(i)].l<=r) add(l,r,rs(i),k);
	line_tree[i].sum=(line_tree[ls(i)].sum+line_tree[rs(i)].sum)%p;
	
}

int query1(int x,int y){
	
	int ans=0;
	while(top[x]!=top[y])
	{
		if(deep[top[x]]<deep[top[y]]) swap(x,y);
		ans+=search(dfn[top[x]],dfn[x],1);
		ans%=p;
		x=fa[top[x]];
	}
	if(deep[x]>deep[y]) swap(x,y);
	ans+=search(dfn[x],dfn[y],1);
	return ans%p;
	
}

void Tup1(int x,int y,int k){
	
	while(top[x]!=top[y])
	{
		if(deep[top[x]]<deep[top[y]]) swap(x,y);
		add(dfn[top[x]],dfn[x],1,k);
		x=fa[top[x]];
	}
	if(deep[x]>deep[y]) swap(x,y);
	add(dfn[x],deep[y],1,k);
	
}

int query2(int root){
	
	return search(dfn[root],dfn[root]+size[root]-1,1);
	
}

void Tup2(int root,int k){
	
	add(dfn[root],dfn[root]+size[root]-1,1,k);
	
}

void add_edge(int x,int y){
	
	edge[cnt].v=y;
	edge[cnt].next=head[x];
	head[x]=cnt++;
	
}

void dfs1(int u,int dep){
	
	deep[u]=dep;
	size[u]=1;
	hson[u]=0;
	for(int i=head[u];i;i=edge[i].next)
	{
		int v=edge[i].v;
		if(deep[v]) continue;
		dfs1(v,dep+1);
		size[u]+=size[v];
		fa[v]=u;
		if(size[v]>size[hson[v]])
			hson[u]=v;
	}
	
}

void dfs2(int u,int t){
	
	top[u]=t;
	dfn[u]=++tot;
	ndata[tot]=data[u];
	if(!hson[u]) return ;
	dfs2(hson[u],t);
	for(int i=head[u];i;i=edge[i].next)
		if(edge[i].v!=hson[u]&&edge[i].v!=fa[u]) dfs2(edge[i].v,edge[i].v);
		
}

int main(){
	
	int n,m,r;
	scanf("%d%d%d%d",&n,&m,&r,&p);
	
	for(int i=1;i<=n;i++)
		scanf("%d",&data[i]);
	for(int i=1;i<n;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		add_edge(x,y);
		add_edge(y,x);
	}
	
	size[0]=-1;
	dfs1(r,1);
	dfs2(r,r);
	build(1,n,1);
	
	while(m--)
	{
		int opt,x,y,z;
		scanf("%d",&opt);
		if(opt==1) scanf("%d%d%d",&x,&y,&z),Tup1(x,y,z);
		if(opt==2) scanf("%d%d",&x,&y),printf("%d\n",query1(x,y)%p);
		if(opt==3) scanf("%d%d",&x,&z),Tup2(x,z);
		if(opt==4) scanf("%d",&x),printf("%d\n",query2(x)%p);
	}
	
	return 0;
	
	
}

感谢大佬

2021/7/22 16:42
加载中...