BaiBaiShaFeng @ 2024-12-19 19:30:10
#include <bits/stdc++.h>
#define lc k*2
#define rc k*2+1
using namespace std;
int n, m, r, p, cnt=0;
const int MN=1e5+115;
struct EDGE{
int to, nex, beg, w;
}edge[MN];
void add_node(int x, int y){
cnt++;
edge[cnt].to=y;
edge[cnt].nex=edge[x].beg;
edge[x].beg=cnt;
return;
}
struct STN{
int l, r, val, tag;
}tr[MN*4];
int wt[MN], w[MN];
int res=0;
int son[MN], id[MN], father[MN], tot, dep[MN], size[MN], top[MN];
void pushup(int k){
tr[k].val=(tr[lc].val+tr[rc].val)%p;
return;
}
void build(int k, int l, int r){
tr[k].l=l; tr[k].r=r;
if(l==r){
tr[k].val=wt[l];
if(tr[k].val>p){tr[k].val%=p;}
return;
}
int mid=(l+r)>>1;
build(lc,l,mid);build(rc,mid+1,r);
pushup(k);
return;
}
void pushdown(int k){
if(tr[k].tag){
tr[lc].tag+=tr[k].tag;
tr[rc].tag+=tr[k].tag;
tr[lc].val+=tr[k].tag*(tr[lc].r-tr[lc].l+1);
tr[rc].val+=tr[k].tag*(tr[rc].r-tr[rc].l+1);
tr[lc].val%=p;
tr[rc].val%=p;
tr[k].tag=0;
}
}
void update(int k, int l, int r, int v){
if(tr[k].l>=l&&tr[k].r<=r){
tr[k].val+=v*(tr[k].r-tr[k].l+1);
tr[k].tag+=v;
}else{
pushdown(k);
int mid=(tr[k].l+tr[k].r)>>1;
if(mid>=l){
update(lc,l,r,v);
}
if(mid<r){
update(rc,l,r,v);
}
pushup(k);
}
}
void query(int k, int l, int r){
if(tr[k].l>=l&&tr[k].r<=r){
res+=tr[k].val;
res%=p;
return;
}
pushdown(k);
int mid=(tr[k].l+tr[k].r)>>1;
if(mid>=l){
query(lc,l,r);
}
if(mid<r){
query(rc,l,r);
}
}
void dfs1(int x, int f, int depth){
dep[x]=depth;father[x]=f;size[x]=1;
int bs=-1;
for(int i=edge[x].beg;i;i=edge[i].nex){
int y=edge[i].to;
if(y==f){
continue;
}
dfs1(y,x,depth+1);
size[x]+=size[y];
if(size[y]>bs){
son[x]=y;
bs=size[y];
}
}
return;
}
void dfs2(int x, int topf){//我讨厌树链剖分呜呜呜
id[x]=++tot;wt[tot]=w[x];top[x]=topf;
if(!son[x]){
return;
}
dfs2(son[x],topf);
for(int i=edge[x].beg;i;i=edge[i].nex){
int y=edge[i].to;
if(y==father[x]||y==son[x]){
continue;
}
dfs2(y,y);
}
return;
}
//难绷的来了
int Range(int x, int y){
int ans=0;
while(top[x]!=top[y]){//两点不同链
if(dep[top[x]]<dep[top[y]]){
swap(x,y);
}
res=0;
query(1,id[top[x]],id[x]);ans+=res;ans%=p;
x=father[top[x]];//x跳到顶上
}
//马上处就停了
if(dep[x]>dep[y]){
swap(x,y);
}
res=0;
query(1,id[x],id[y]);
ans+=res;
return ans%p;
}
void Change(int x, int y, int k){
k%=p;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
swap(x,y);
}
update(1,id[top[x]],id[x],k);
x=father[top[x]];
}
if(dep[x]>dep[y]){
swap(x,y);
}
update(1,id[x],id[y],k);
return;
}
int Son(int x){
res=0;
query(1,id[x],id[x]+size[x]-1);
return res;
}
void cSon(int x, int k){
update(1,id[x],id[x]+size[x]-1,k);
return;
}
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);
add_node(a,b);
add_node(b,a);
}
dfs1(r,0,1);
dfs2(r,r);
build(1,1,n);
for(int i=1; i<=m; i++){
int op;
scanf("%d",&op);
if(op==1){
int a, b, c;
scanf("%d%d%d",&a,&b,&c);
Change(a,b,c);
}else if(op==2){
int a, b;
scanf("%d%d",&a,&b);
printf("%d\n",Range(a,b));
}else if(op==3){
int a, b;
scanf("%d%d",&a,&b);
cSon(a,b);
}else{
int a;
scanf("%d",&a);
printf("%d\n",Son(a));
}
}
return 0;
}
by xpigeon @ 2024-12-19 19:48:25
你小子效率也太高了
by Poole_tea @ 2024-12-19 20:03:36
for(int i=1; i<=n; i++){
int a, b;
scanf("%d%d",&a,&b);
add_node(a,b);
add_node(b,a);
}
这不应该是输入
by BaiBaiShaFeng @ 2024-12-19 20:13:05
@Poole_tea 谢谢哦, 一不小心脑残了, 这个连数据都输入不了的代码竟然可以得10分(⊙﹏⊙)