代码应该是正确的,但是操作一操作二跑的太慢了
丑陋的代码
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
struct Seg_Tree{
int l,r,s,add;
}dat[MAXN*4];
int n,m,rt,mod,cnt;
vector<int>G[MAXN];
int id[MAXN],top[MAXN],son[MAXN],siz[MAXN],p[MAXN],dep[MAXN],a[MAXN];
void build(int l,int r,int k){
dat[k].l=l;dat[k].r=r;
if(l==r)return ;
int m=(l+r)/2;
build(l,m,k+k);
build(m+1,r,k+k+1);
}
void update(int x,int y,int z,int k){
if(dat[k].l==x&&dat[k].r==y){
dat[k].add=(dat[k].add+z)%mod;
return ;
}
int m=(dat[k].l+dat[k].r)/2;
dat[k].s=(dat[k].s+(y-x+1)*z)%mod;
if(y<=m)update(x,y,z,k+k);
else if(x>m)update(x,y,z,k+k+1);
else update(x,m,z,k+k),update(m+1,y,z,k+k+1);
}
int query(int x,int y,int p,int k){
p=(p+dat[k].add)%mod;
if(dat[k].l==x&&dat[k].r==y)return (p*(y-x+1)+dat[k].s)%mod;
int m=(dat[k].l+dat[k].r)/2;
if(y<=m)return query(x,y,p,k+k);
else if(x>m)return query(x,y,p,k+k+1);
else return (query(x,m,p,k+k)+query(m+1,y,p,k+k+1))%mod;
}
void dfs1(int x,int pre){
p[x]=pre;siz[x]=1;dep[x]=dep[pre]+1;
int l=G[x].size();
int mxl=0;
for(int i=0;l>i;i++)
if(G[x][i]!=pre){
int y=G[x][i];
dfs1(y,x);
siz[x]+=siz[y];
if(G[y].size()>=mxl)son[x]=y,mxl=G[y].size();
}
}
void dfs2(int x,int t){
id[x]=++cnt;
top[x]=t;
if(a[x]!=0)update(id[x],id[x],a[x],1);
if(son[x]==0)return ;
dfs2(son[x],t);
int l=G[x].size();
for(int i=0;l>i;i++){
int y=G[x][i];
if(id[y])continue;
dfs2(y,y);
}
}
void addpath(int x,int y,int z){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
update(id[top[x]],id[x],z,1);
x=p[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
update(id[x],id[y],z,1);
}
int querypath(int x,int y){
int res=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
res=(res+query(id[top[x]],id[x],0,1))%mod;
x=p[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
res=(res+query(id[x],id[y],0,1))%mod;
return res;
}
void addtree(int x,int z){
update(id[x],id[x]+siz[x]-1,z,1);
}
int querytree(int x){
return query(id[x],id[x]+siz[x]-1,0,1);
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m>>rt>>mod;
for(int i=1;n>=i;i++)cin>>a[i];
int x,y,z;
for(int i=1;n>i;i++){
cin>>x>>y;
G[x].push_back(y);
G[y].push_back(x);
}
build(1,n,1);
dfs1(rt,0);
dfs2(rt,rt);
int k;
for(int i=0;m>i;i++){
cin>>k;
if(k==1){
cin>>x>>y>>z;
addpath(x,y,z);
}else if(k==2){
cin>>x>>y;
cout<<querypath(x,y)%mod<<endl;
}else if(k==3){
cin>>x>>z;
addtree(x,z);
}else{
cin>>x;
cout<<querytree(x)%mod<<endl;
}
}
return 0;
}