• 1 x y z,表示将树从 xx 到 yy 结点最短路径上所有节点的值都加上 zz。

  • 2 x y,表示求树从 xx 到 yy 结点最短路径上所有节点的值之和。

  • 3 x z,表示将以 xx 为根节点的子树内所有节点值都加上 zz。

  • 4 x 表示求以 xx 为根节点的子树内所有节点值之和

 

#include <bits/stdc++.h>
using namespace std ;
 const int N=2e5+5,M=N;
 #define int long long
 int S,mod;
 
 
 int n,nxt[M],hd[N],all,go[M];
 int dep[N],sz[N],fa[N],son[N];
 int dfn[N],id[N],pool,top[N];
 
#define k1 k<<1
#define k2 k<<1|1

  int a[N];
  struct Tree{
  	int s,lazy;
  	int l,r;
  }tr[N<<2];
 
 void help(int k,int v){
 	tr[k].lazy+=v, tr[k].s+=v*(tr[k].r-tr[k].l+1);
    tr[k].lazy%=mod; tr[k].s%=mod;
 }
 void pushd(int k){
     if(tr[k].lazy==0) return;
     
     help(k1,tr[k].lazy),help(k2,tr[k].lazy); 
     tr[k].lazy=0;
 }
 int qry(int k,int x,int y){
     int t=0;
     if(x<=tr[k].l&&y>=tr[k].r)
         return tr[k].s%mod;
     
     int md=(tr[k].l+tr[k].r)/2; 
     pushd(k);
     if(x<=md) t+=qry(k1,x,y),t%=mod;
     if(y>md) t+=qry(k2,x,y),t%=mod;
     return t;
 }
 void add(int k,int x,int y,int z){
     if(x<=tr[k].l&&y>=tr[k].r) return help(k,z);
     
     int md=(tr[k].l+tr[k].r)/2;
     pushd(k);
     if(x<=md) add(k1,x,y,z);
    if(y>md) add(k2,x,y,z);
    
     tr[k].s=tr[k1].s+tr[k2].s,tr[k].s%=mod;
 }
 void build(int k,int l,int r){
 	tr[k].l=l,tr[k].r=r;
 	tr[k].s=0;
 	
     if(l==r){
         tr[k].s=a[id[l]]; tr[k].s%=mod; return;
     }
     int md=(l+r)/2;
     build(k1,l,md),build(k2,md+1,r);
     
    tr[k].s=tr[k1].s+tr[k2].s,tr[k].s%=mod;
 }


 
 void add(int x,int y){
 	go[++all]=y,nxt[all]=hd[x],hd[x]=all;
 }
 void dfs1(int x,int par){
 	fa[x]=par;
 	sz[x]=1;
 	dep[x]=dep[par]+1;
 	son[x]=0;
 	
 	for(int i=hd[x];i;i=nxt[i]){
 		int y=go[i]; if(par==y) continue;
		  dfs1(y,x);
 		sz[x]+=sz[y];
 		if(sz[y]>sz[son[x]]) son[x]=y;
	 }
 }
 void dfs2(int x,int topf){
 	dfn[x]=++pool;
 	id[pool]=x;
 	top[x]=topf;
 	if(!son[x]) return ;
 	dfs2(son[x],topf);
 	
 	for(int i=hd[x];i;i=nxt[i]){
 		int y=go[i]; 
 		if(y==fa[x]||y==son[x]) continue;
		  dfs2(y,y);
	 }
 }
 int qRange(int x,int y){
 	int res=0;
 	while(top[x]!=top[y]){
 		if(dep[top[x]]<dep[top[y]]) swap(x,y);
 		res+=qry(1,dfn[top[x]],dfn[x]); res%=mod;
 		
 		x=fa[top[x]];
	 }
	if(dep[x]>dep[y]) swap(x,y);
	res+=qry(1,dfn[x],dfn[y]); res%=mod;
	return res;
 }
 void upRange(int x,int y,int z){
 	z%=mod;
 	while(top[x]!=top[y]){
 		if(dep[top[x]]<dep[top[y]]) swap(x,y);
 		add(1,dfn[top[x]],dfn[x],z);
 		
 		x=fa[top[x]];
	 }
	 if(dep[x]>dep[y]) swap(x,y);
	 add(1,dfn[x],dfn[y],z);
 }
 int qSon(int x){
 	return qry(1,dfn[x],dfn[x]+sz[x]-1)%mod;
 }
 void upSon(int x,int z){
 	z%=mod;
 	add(1,dfn[x],dfn[x]+sz[x]-1,z);
 }
 signed main(){
 	int op,i,x,y,z,tes;
 
 	cin>>n>>tes>>S>>mod;
 	for(i=1;i<=n;i++) cin>>a[i];
 	for(i=1;i<n;i++) cin>>x>>y,add(x,y),add(y,x);
 	
 	dfs1(S,0); dfs2(S,S);
 	build(1,1,n);
 	
 	while(tes--){
 		cin>>op;
 		if(op==1){
 			cin>>x>>y>>z;
 			upRange(x,y,z);
		 }
		else if(op==2){
			cin>>x>>y;
			cout<<qRange(x,y)<<endl;

		}
		else if(op==3){
			cin>>x>>y;
			upSon(x,y);
		}
		else if(op==4){
			cin>>x;
			cout<<qSon(x)<<endl;
		}
	 }
 } 
 
 

 

posted on 2023-03-10 20:48  towboat  阅读(14)  评论(0)    收藏  举报