社区讨论

萌新刚学OI,树链剖分莫名写炸求救

P3384【模板】重链剖分 / 树链剖分参与者 4已保存回复 8

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
8 条
当前快照
1 份
快照标识符
@mi86bc4r
此快照首次捕获于
2025/11/21 09:20
4 个月前
此快照最后确认于
2025/11/21 09:20
4 个月前
查看原帖
RT,不知为何MLE
CPP
#include <bits/stdc++.h>
using namespace std;
const int N=100005;
#define ll long long
int dep[N],siz[N],fa[N],z[N],to[N<<1],beg[N<<1],nxt[N<<1],top[N<<2],bian,son[N<<1],id[N<<1],tot,n,m,r,mod;
struct Tree{
    ll ans[N<<2],tag[N<<2],a[N];
    inline ll lson(ll p){return p<<1;}
    inline ll rson(ll p){return (p<<1)|1;}
    inline void push_up(ll p){ans[p]=(ans[lson(p)]+ans[rson(p)])%mod;}
    inline void build(ll p,ll l,ll r){
        if (l==r){ans[p]=a[l];return ;}
        ll mid=(l+r)>>1;
        build(lson(p),l,mid);
        build(rson(p),mid+1,r);
        push_up(p);
        tag[p]=0;
    }
    inline void lazy_tag(ll p,ll l,ll r,ll k){ans[p]=(ans[p]+(r-l+1)*k)%mod,tag[p]=(tag[p]+k)%mod;}
    inline void push_down(ll p,ll l,ll r){
        ll mid=(l+r)>>1;
        lazy_tag(lson(p),l,mid,tag[p]);
        lazy_tag(rson(p),mid+1,r,tag[p]);
        tag[p]=0;
    }
    inline void change(ll p,ll nl,ll nr,ll l,ll r,ll k){//nl,nr->changing l,changing r;l,r->visiting l,visiting r
        if (nl<=l&&nr>=r){ans[p]=(ans[p]+(r-l+1)*k)%mod,tag[p]=(tag[p]+k)%mod;return ;}
        ll mid=(l+r)>>1;
        push_down(p,l,r);
        if (nl<=mid)change(lson(p),nl,nr,l,mid,k);
        if (nr>mid)change(rson(p),nl,nr,mid+1,r,k);
        push_up(p);
    }
    inline ll ask(ll p,ll nl,ll nr,ll l,ll r){
        if (nl<=l&&nr>=r)return ans[p];
        ll mid=(l+r)>>1,res=0;
        push_down(p,l,r);
        if (nl<=mid)res=(res+ask(lson(p),nl,nr,l,mid))%mod;
        if (nr>mid)res=(ask(rson(p),nl,nr,mid+1,r))%mod;
        return res;
    }
}tree;
inline void add(int u,int v){
    to[++bian]=v;
    nxt[bian]=beg[u];
    beg[u]=bian;
}
inline void dfs1(int x){
    siz[x]=1;
    for (int i=beg[x];i;i=nxt[i]){
        if (to[i]==fa[x])continue;
        fa[to[i]]=x;
        dep[to[i]]=dep[x]+1;
        dfs1(to[i]);
        siz[x]+=siz[to[i]];
        if (siz[to[i]]>siz[son[x]])son[x]=to[i];
    }
}
inline void dfs2(int x,int y){
    top[x]=y;id[x]=++tot;
    if (son[x])dfs2(son[x],y);
    for (int i=beg[x];i;i=nxt[i]){
        if (to[i]==fa[i]||to[i]==son[i])continue;
        dfs2(to[i],to[i]);
    }
}
int query(int x,int y){
    int ans=0;
    while (top[x]!=top[y]){
        if (dep[top[x]]<dep[top[y]])swap(x,y);
        ans=(ans+tree.ask(r,id[top[x]],id[x],1,n))%mod;
        x=fa[top[x]];
    }
    if (dep[x]<dep[y])swap(x,y);
    ans=(ans+tree.ask(r,id[y],id[x],1,n));
    return ans;
}
void chge(int x,int y,int k){
    k%=mod;
    while (top[x]!=top[y]){
        if (dep[top[x]]<dep[top[y]])swap(x,y);
        tree.change(r,id[top[x]],id[x],1,n,k);
        x=fa[top[x]];
    }
    if (dep[x]<dep[y])swap(x,y);
    tree.change(r,id[y],id[x],1,n,k);
}
int main(){
    scanf ("%lld%lld%lld%lld",&n,&m,&r,&mod);fa[r]=0,dep[r]=1;
    for (int i=1;i<=n;i++)scanf ("%lld",&tree.a[i]);
    for (int i=1;i<n;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b),add(b,a);
    }
    dfs1(r);
    dfs2(r,r);
    tree.build(1,1,n);
    while(m--){
        int flag,x,y,k;
        scanf ("%d",&flag);
        switch (flag){
            case 1:scanf ("%d%d%d",&x,&y,&k);chge(x,y,k);break;
            case 2:scanf ("%d%d",&x,&y);printf("%lld\n",query(x,y));break;
            case 3:scanf ("%d%d",&x,&k);tree.change(1,id[x],id[x]+siz[x]-1,1,n,k);break;
            case 4:scanf ("%d",&x);printf("%lld\n",tree.ask(1,id[x],id[x]+siz[x]-1,1,n));
        }
    }
}
忽略我封装的线段树好吧

回复

8 条回复,欢迎继续交流。

正在加载回复...