严重怀疑我的子树修改查询.
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+7;
int N,M,R,P,w[maxn],dep[maxn];
int head[maxn],nxt[maxn],to[maxn],cnt;//邻接表全家桶
int Fa[maxn],Hd[maxn],Hson[maxn],SZ[maxn],id[maxn];
//树剖全家桶(爹,i的重链头,重儿子,子树大小,在线段树的位置 )
struct node{int l,r,dat,add;}tree[maxn];
void edge(int U,int V){
nxt[++cnt]=head[U];to[cnt]=V;head[U]=cnt;
nxt[++cnt]=head[V];to[cnt]=U;head[V]=cnt;
return;
}
//以下为线段树
int ls(int p){return p<<1;}
int rs(int p){return (p<<1)|1;}
int Len(int p){return tree[p].r-tree[p].l+1;}
int Mid(int l,int r){return (l+r)>>1;}
void pushdown(int p){//懒标记
if(tree[p].add){
tree[ls(p)].add+=tree[p].add;
tree[rs(p)].add+=tree[p].add;
tree[ls(p)].dat+=tree[p].add*Len(ls(p));
tree[rs(p)].dat+=tree[p].add*Len(rs(p));
tree[ls(p)].dat%=P;tree[rs(p)].dat%=P;
tree[p].add=0;
}
return;
}
void build(int l,int r,int p){//建树
tree[p].l=l;tree[p].r=r;
if(l==r){tree[p].dat=w[l]%P;return;}
int mid=Mid(l,r);
build(l,mid,ls(p));build(mid+1,r,rs(p));
tree[p].dat=(tree[ls(p)].dat+tree[rs(p)].dat)%P;
return;
}
void change(int p,int l,int r,int k){
if(l<=tree[p].l&&tree[p].r<=r){
tree[p].dat+=1LL*k*Len(p);
tree[p].dat%=P;
tree[p].add+=k;
tree[p].add%=P;
return;
}
pushdown(p);
int mid=Mid(tree[p].l,tree[p].r);
if(l<=mid)change(ls(p),l,r,k);
if(r>mid)change(rs(p),l,r,k);
tree[p].dat=(tree[ls(p)].dat+tree[rs(p)].dat)%P;
return;
}
long long query(int p,int l,int r){
if(l<=tree[p].l&&r>=tree[p].r)return tree[p].dat%P;
pushdown(p);
int mid=Mid(tree[p].l,tree[p].r);
long long ret=0;
if(l<=mid)ret+=query(ls(p),l,r);
if(r>mid)ret+=query(rs(p),l,r);
return ret%P;
}
//线段树部分结束
//它 来 了
int dfs1(int u,int fa){
int maxson=-1;
SZ[u]=1;Fa[u]=fa;dep[u]=dep[fa]+1;
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(v==fa)continue;
SZ[u]+=dfs1(v,u);
if(SZ[v]>maxson)maxson=SZ[v],Hson[u]=v;
}
return SZ[u];
}
void dfs2(int u,int fa,int top){//当前节点,爹,重链头
id[u]=++cnt;Hd[u]=top;
w[cnt]=w[u];
if(!Hson[u])return;
dfs2(Hson[u],u,top);
for(int i=head[u];i;i=nxt[i])
if(to[i]!=fa&&to[i]!=Hson[u])dfs2(to[i],u,to[i]);
return;
}
void addTree(int u,int v,int W){
W%=P;
while(Hd[u]!=Hd[v]){
if(dep[Hd[u]]<dep[Hd[v]])swap(u,v);
change(1,id[Hd[u]],id[u],W);
u=Fa[Hd[u]];
}
if(dep[u]>dep[v])swap(u,v);
change(1,id[u],id[v],W);
return;
}
int queryTree(int u,int v){
int ret=0;
while(Hd[u]!=Hd[v]){
if(dep[Hd[u]]<dep[Hd[v]])swap(u,v);
ret+=query(1,id[Hd[u]],id[u]);ret%=P;
u=Fa[Hd[u]];
}
if(dep[u]>dep[v])swap(u,v);
ret+=query(1,id[u],id[v]);
return ret%P;
}
//E · N · D
int main(){
scanf("%d%d%d%d",&N,&M,&R,&P);
for(int i=1;i<=N;i++)scanf("%d",&w[i]);
for(int i=1;i<N;i++){int a,b;scanf("%d%d",&a,&b);edge(a,b);}
cnt=0;
dfs1(R,0);
dfs2(R,0,R);
build(1,N,1);
while(M--){
//cout<<"Case "<<M+1<<endl;
int op,x,y,z;
scanf("%d",&op);
if(op==1){
//cout<<"修改\n";
scanf("%d%d%d",&x,&y,&z);
addTree(x,y,z);
}else if(op==2){
//cout<<"查询\n";
scanf("%d%d",&x,&y);
printf("%d\n",queryTree(x,y));
}else if(op==3){
//cout<<"修改\n";
scanf("%d%d",&x,&y);
change(1,id[x],id[x]+SZ[x]-1,y);
}else{
//cout<<"查询\n";
scanf("%d",&x);
printf("%d\n",query(1,id[x],id[x]+SZ[x]-1));
}
}
return 0;
}