啊,,调了很久就是了。
跳链的时候跳的是top的深度大的那个,不是本身深度大的。
我是傻逼。
洛谷树剖模板。
#include<bits/stdc++.h>View Code
using namespace std;
const int N=100010;
typedef long long ll;
inline ll read(){
ll f=1,r=0,c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){r=r*10+c-'0';c=getchar();}
return r*f;
}
struct Edge{
int to,nxt;
}e[N*2];
int head[N],cnt=1;ll P;
void add(int u,int v){
e[cnt]=(Edge){v,head[u]};
head[u]=cnt++;
e[cnt]=(Edge){u,head[v]};
head[v]=cnt++;
}
int siz[N],dep[N],dad[N],son[N];
void dfs1(int u,int fa){
siz[u]=1;dad[u]=fa;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa)continue;
dep[v]=dep[u]+1;dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])
son[u]=v;
}
}
int pos[N],top[N],dfn;
void dfs2(int u,int anc){
top[u]=anc;pos[u]=++dfn;
if(!son[u])return;
dfs2(son[u],anc);
for(int i=head[u];i;i=e[i].nxt)
if(e[i].to^dad[u]&&e[i].to^son[u])
dfs2(e[i].to,e[i].to);
}
#define ls o<<1
#define rs (o<<1)|1
#define L T[o].l
#define R T[o].r
#define M L+R>>1
struct Node{
ll l,r,add,sum;
}T[N*4];
ll a[N],b[N];
void pushdown(int o){
(T[ls].add+=T[o].add)%=P;
(T[rs].add+=T[o].add)%=P;
(T[ls].sum+=(T[ls].r-T[ls].l+1)*T[o].add)%=P;
(T[rs].sum+=(T[rs].r-T[rs].l+1)*T[o].add)%=P;
T[o].add=0;
}
void pullup(int o){
(T[o].sum=T[ls].sum+T[rs].sum)%=P;
}
void build(int o,int l,int r){
if(l==r){
T[o]=(Node){l,r,0,a[l]};
return;
}
T[o]=(Node){l,r,0,0};
build(ls,l,l+r>>1);
build(rs,(l+r>>1)+1,r);
pullup(o);
}
ll val,ans,ql,qr;
void upd(int o){
if(ql<=L&&R<=qr){
(T[o].add+=val)%=P;
(T[o].sum+=(R-L+1)*val)%=P;
return;
}
pushdown(o);
if(ql<=M)upd(ls);
if(qr>M) upd(rs);
pullup(o);
}
void qsum(int o){
if(ql<=L&&R<=qr){
(ans+=T[o].sum)%=P;
return;
}
pushdown(o);
if(ql<=M)qsum(ls);
if(qr>M) qsum(rs);
}
void modify(int u,int v,ll t){
val=t;
while(top[u]^top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
ql=pos[top[u]],qr=pos[u];upd(1);
u=dad[top[u]];
}
if(pos[u]>pos[v])swap(u,v);
ql=pos[u],qr=pos[v];upd(1);
}
void query(int u,int v){
ans=0;
while(top[u]^top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
ql=pos[top[u]],qr=pos[u];qsum(1);
u=dad[top[u]];
}
if(pos[u]>pos[v])swap(u,v);
ql=pos[u],qr=pos[v];qsum(1);
printf("%lld\n",ans%P);
}
int n,m,S;
void init(){
n=read(),m=read(),S=read(),P=read();
for(int i=1;i<=n;i++)b[i]=read();
for(int i=1;i<n;i++)
add(read(),read());
dfs1(S,0);dfs2(S,S);
for(int i=1;i<=n;i++)
a[pos[i]]=b[i];
build(1,1,n);
}
void solve(){
while(m--){
int opt=read();
if(opt==1){
int u=read(),v=read();ll t=read();
modify(u,v,t);
}
else if(opt==2){
int u=read(),v=read();
query(u,v);
}
else if(opt==3){
int u=read();
ql=pos[u],qr=ql+siz[u]-1;
val=read();upd(1);
}
else{
int u=read();
ans=0;
ql=pos[u],qr=ql+siz[u]-1;
qsum(1);
printf("%lld\n",ans%P);
}
}
}
int main(){
init();
solve();
}
感觉150行,3KB左右,字数算不多了,打了几遍也基本记下来了。
upd
又手写了三道,板子没问题了具体问题能不能会做呢?那得问线段树了。。。