qwq拖了这么久总算A掉模板题
我怕不是机房最后一个学树剖的
https://www.cnblogs.com/George1994/p/7821357.html
图论太麻烦了放一个博客吧233
个人感觉是一个可以用来水过一些思维难度高的简单算法题的暴力高级算法quq
还要用数据结构确实挺麻烦的也不好调
顺便附上我A掉的模板题!(luoguP3384)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 100005
#define ls cur<<1
#define rs cur<<1|1
using namespace std;
int n,m,rt,mod,tot,fa[maxn],a[maxn],cnt,head[maxn],dep[maxn],siz[maxn],son[maxn],top[maxn],rk[maxn],id[maxn];
inline int rd(){
int x=0,f=1;char c=' ';
while(c<'0' || c>'9'){if(c=='-') f=-1;c=getchar();}
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
struct EDGE{
int to,nxt;
}edge[maxn<<1];
inline void add(int x,int y){
edge[++cnt].to=y; edge[cnt].nxt=head[x]; head[x]=cnt;
}
inline void dfs1(int u,int father,int depth){
dep[u]=depth; fa[u]=father; siz[u]=1;
int maxson=-1;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==father) continue;
dfs1(v,u,depth+1);
siz[u]+=siz[v];
if(siz[v]>maxson) son[u]=v,maxson=siz[v];
} return;
}
inline void dfs2(int u,int t){
top[u]=t; id[u]=++tot; rk[tot]=u;
if(!son[u]) return;
dfs2(son[u],t);
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v!=son[u] && v!=fa[u]) dfs2(v,v);
}
}
struct NODE{
int sum,lazy,l,r;
}node[maxn<<2];//这里要开4倍!
inline void pushup(int cur){
node[cur].l=node[ls].l; node[cur].r=node[rs].r;
node[cur].sum=(node[ls].sum+node[rs].sum)%mod;
}
inline void build(int cur,int L,int R){
if(L==R){
node[cur].l=node[cur].r=L; node[cur].sum=a[rk[L]];
return;
}
int mid=(L+R)>>1;
build(ls,L,mid); build(rs,mid+1,R);
pushup(cur);
}
inline void pushdown(int cur){
(node[ls].sum+=node[cur].lazy*((node[ls].r-node[ls].l+1)%mod)%mod)%=mod;
(node[rs].sum+=node[cur].lazy*((node[rs].r-node[rs].l+1)%mod)%mod)%=mod;
(node[ls].lazy+=node[cur].lazy)%=mod;
(node[rs].lazy+=node[cur].lazy)%=mod;
node[cur].lazy=0;
}
inline void update(int cur,int L,int R,int c){
if(L<=node[cur].l && node[cur].r<=R){
(node[cur].sum+=c*((node[cur].r-node[cur].l+1)%mod)%mod)%=mod;
(node[cur].lazy+=c)%=mod; return;
}
pushdown(cur);
int mid=(node[cur].l+node[cur].r)>>1;
if(L<=mid) update(ls,L,R,c);
if(mid<R) update(rs,L,R,c);
pushup(cur);
}
inline int query(int cur,int L,int R){
if(L<=node[cur].l && node[cur].r<=R)
return node[cur].sum;
pushdown(cur);
int res=0;
int mid=(node[cur].l+node[cur].r)>>1;
if(L<=mid) (res+=query(ls,L,R))%=mod;
if(mid<R) (res+=query(rs,L,R))%=mod;
return res;
}
inline int ask(int x,int y){
int ans=0,fx=top[x],fy=top[y];
while(fx!=fy){
if(dep[fx]>=dep[fy]) {
(ans+=query(1,id[fx],id[x]))%=mod;
x=fa[fx];
}
else{
(ans+=query(1,id[fy],id[y]))%=mod;
y=fa[fy];
}
fx=top[x]; fy=top[y];
}
if(id[x]<=id[y]) (ans+=query(1,id[x],id[y]))%=mod;
else (ans+=query(1,id[y],id[x]))%=mod;
return ans;
}
inline void change(int x,int y,int c){
int fx=top[x],fy=top[y];
while(fx!=fy){
if(dep[fx]>=dep[fy]){
update(1,id[fx],id[x],c);
x=fa[fx];
}
else{
update(1,id[fy],id[y],c);
y=fa[fy];
}
fx=top[x]; fy=top[y];
}
if(id[x]<=id[y]) update(1,id[x],id[y],c);
else update(1,id[y],id[x],c);
}
int main(){
n=rd(); m=rd(); rt=rd(); mod=rd();
for(int i=1;i<=n;i++) a[i]=rd();
for(int i=1;i<n;i++){
int x=rd(),y=rd();
add(x,y); add(y,x);
}
dfs1(rt,0,1);
dfs2(rt,rt);
build(1,1,n);
while(m--){
int opt,x,y,z;
opt=rd();
if(opt==1){
x=rd(); y=rd(); z=rd();
change(x,y,z);
}
else if(opt==2){
x=rd(),y=rd();
printf("%d\n",ask(x,y));
}
else if(opt==3){
x=rd(),z=rd();
update(1,id[x],id[x]+siz[x]-1,z);
}
else{
x=rd();
printf("%d\n",query(1,id[x],id[x]+siz[x]-1));
}
}
return 0;
}