傻逼调了一天树剖

时间:2022-10-13 16:08:18

啊,,调了很久就是了。

跳链的时候跳的是top的深度大的那个,不是本身深度大的。

我是傻逼。

洛谷树剖模板。

傻逼调了一天树剖傻逼调了一天树剖
#include<bits/stdc++.h>
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();
}
View Code

感觉150行,3KB左右,字数算不多了,打了几遍也基本记下来了。


upd

又手写了三道,板子没问题了具体问题能不能会做呢?那得问线段树了。。。