树剖调不出来,求助

P3384 【模板】重链剖分/树链剖分

Kketchup @ 2022-12-28 21:02:37

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ls p<<1
#define rs p<<1|1
const int N=1e5+10;
int n,m,r,mod;
int a[N],op,x,y,k;
struct edge{int v,next;}e[N<<1];
int head[N],tot;
inline void add(int u,int v){e[tot].v=v,e[tot].next=head[u],head[u]=tot++;}
int siz[N],top[N],fa[N],son[N],deep[N],ne[N],id[N],cnt;
void dfs1(int u,int f,int dep){
    deep[u]=dep,siz[u]=1,fa[u]=f,son[u]=0;
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==f) continue;
        dfs1(v,u,dep+1),siz[u]+=siz[v];
        if(!son[u]||siz[v]>siz[son[u]]) son[u]=v;
    }
}void dfs2(int u,int topx){
    id[u]=++cnt,ne[cnt]=a[u],top[u]=topx;
    if(!son[u]) return ;
    dfs2(son[u],topx);
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
    }
}struct segment{int l,r,dat,lazy;}t[N<<2];
inline void pushup(int p){t[p].dat=(t[ls].dat+t[rs].dat)%mod;}
inline void pushdown(int p){
    if(t[p].lazy){
        t[ls].lazy=(t[ls].lazy+t[p].lazy)%mod;
        t[rs].lazy=(t[ls].lazy+t[p].lazy)%mod;
        t[ls].dat=(t[ls].dat+t[p].lazy*(t[ls].r-t[ls].l+1))%mod;
        t[rs].dat=(t[rs].dat+t[p].lazy*(t[rs].r-t[rs].l+1))%mod;
        t[p].lazy=0;
    }
}
void build(int p,int l,int r){
    t[p].l=l,t[p].r=r;
    if(l==r){t[p].dat=ne[l]%mod;return ;}
    int mid=(l+r)>>1;
    build(ls,l,mid),build(rs,mid+1,r);
    pushup(p);
}void update(int p,int l,int r,int k){
    if(l<=t[p].l&&t[p].r<=r){
        t[p].dat=(t[p].dat+(t[p].r-t[p].l+1)*k)%mod;
        t[p].lazy=(t[p].lazy+k)%mod;
        return ;
    }pushdown(p);
    int mid=(t[p].l+t[p].r)>>1;
    if(l<=mid) update(ls,l,r,k);
    if(mid+1<=r) update(rs,l,r,k);
    pushup(p);
}int sum(int p,int l,int r){
    if(l<=t[p].l&&t[p].r<=r) return t[p].dat%mod;
    pushdown(p);
    int mid=(t[p].l+t[p].r)>>1,ans=0;
    if(l<=mid) ans+=sum(ls,l,r);
    if(mid+1<=r) ans+=sum(rs,l,r);
    return ans%mod;
}inline void modify(int x,int y,int k){
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        update(1,id[top[x]],id[x],k),x=fa[top[x]];
    }if(deep[x]>deep[y]) swap(x,y);
    update(1,id[x],id[y],k);
}inline int query(int x,int y){
    int ans=0;
    while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        ans+=sum(1,id[top[x]],id[x]),ans%=mod,x=fa[top[x]];
    }if(deep[x]>deep[y]) swap(x,y);
    ans+=sum(1,id[x],id[y]);return ans%mod;
}
int main(){
    memset(head,-1,sizeof(head)),tot=0;
    scanf("%d%d%d%d",&n,&m,&r,&mod);
    for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    for(int i=1;i<n;++i) scanf("%d%d",&x,&y),add(x,y),add(y,x);
    dfs1(r,0,1),dfs2(r,r),build(1,1,n);
    while(m--){
        scanf("%d",&op);
        if(op==1) scanf("%d%d%d",&x,&y,&k),modify(x,y,k);
        if(op==2) scanf("%d%d",&x,&y),printf("%d\n",query(x,y));
        if(op==3) scanf("%d%d",&x,&y),update(1,id[x],id[x]+siz[x]-1,y);
        if(op==4) scanf("%d",&x),printf("%d\n",sum(1,id[x],id[x]+siz[x]-1));
    }
    return 0;
}

求助dalao


by phil071128 @ 2022-12-29 08:12:06

@JKYak 树剖没炸,线段树炸了。


by Kketchup @ 2022-12-29 10:38:07

天,我的segment tree/kk


|