TLE疑似死循环悬棺求助

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

Kniqht @ 2023-12-30 16:06:35

rt,不知道哪里写挂了,三个点AC 5ms别的都T了,很抽象,悬赏本号的关注/kk

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+10,M=4e5+10;
int n,m,R;ll mod;
int h[N],e[M*2],ne[M*2],idx;
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
} 
int dep[N],fa[N],sz[N],top[N],son[N];
int id[N],cnt;
ll w[N],nw[N];
struct Nd{
    int l,r;
    ll add,v;
}tr[N*4];
void dfs1(int u,int father,int depth){
    dep[u]=depth,fa[u]=father,sz[u]=1;
    for(int i=h[u];~i;i=ne[i]){
        int j=e[i];
        if(j==father) continue;
        dfs1(j,u,depth+1);
        sz[u]+=sz[j];
        if(sz[j]>sz[son[u]]) son[u]=j;
    }
} 
void dfs2(int u,int t){
    id[u]=++cnt,nw[cnt]=w[u],top[u]=t;
    if(!son[u]) return;
    dfs2(son[u],t);
    for(int i=h[u];~i;i=ne[i]){
        int j=e[i];
        if(j==fa[u]||j==son[u]) continue;
        dfs2(j,j);
    }
}
void pushup(int u){
    tr[u].v=(tr[u<<1].v+tr[u<<1|1].v)%mod;
}
void pushdown(int u){
    Nd &rt=tr[u],&lc=tr[u<<1],&rc=tr[u<<1|1];
    if(!rt.add) return;
    lc.add=(lc.add+rt.add)%mod;rc.add=(rc.add+rt.add)%mod;
    lc.v=(lc.v+(ll)(lc.r-lc.l+1)*rt.add%mod)%mod;
    rc.v=(rc.v+(ll)(rc.r-rc.l+1)*rt.add%mod)%mod;
    rt.add=0;
}
void build(int u,int l,int r){
    tr[u]={l,r,0,nw[r]};
    if(l==r) return;
    int mid=l+r>>1;
    build(u<<1,l,mid);build(u<<1|1,mid+1,r);
    pushup(u);
}
void update(int u,int l,int r,ll k){
    if(tr[u].l>r||tr[u].r<l) return;
    if(tr[u].l>=l&&tr[u].r<=r){
        tr[u].add=(tr[u].add+k)%mod;
        tr[u].v=(tr[u].v+(ll)(tr[u].r-tr[u].l+1)*k%mod)%mod;
        return;
    }
    pushdown(u);
    update(u<<1,l,r,k);update(u<<1|1,l,r,k);
    pushup(u);
}
ll query(int u,int l,int r){
    if(tr[u].l>r||tr[u].r<l) return 0;
    if(tr[u].l>=l&&tr[u].r<=r) return tr[u].v%mod;
    pushdown(u);
    return (query(u<<1,l,r)+query(u<<1|1,l,r))%mod;
    pushup(u);
}
void update_path(int u,int v,int k){
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        update(1,id[top[u]],id[u],k);
        u=fa[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    update(1,id[v],id[u],k);
}
ll get_path(int u,int v){
    ll res=0;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        res=(res+query(1,id[top[u]],id[u]))%mod;
        u=fa[top[u]];
    }
    if(dep[u]<dep[v]) swap(u,v);
    res=(res+query(1,id[v],id[u]))%mod;
    return res;
}
ll get_tree(int u){
    return query(1,id[u],id[u]+sz[u]-1);
}
void update_tree(int u,ll k){
    update(1,id[u],id[u]+sz[u]-1,k);
} 
signed main(){
    scanf("%d%d%d%d",&n,&m,&R,&mod);
    for(int i=1;i<=n;i++) scanf("%lld",&w[i]),w[i]%=mod;
    memset(h,-1,sizeof(h));int a,b;
    for(int i=1;i<n;i++){
        scanf("%d%d",&a,&b);
        add(a,b);add(b,a);
    }
    dfs1(R,-1,1);dfs2(R,1);build(1,1,n);
    while(m--){
        int t,u,v,k;
        scanf("%d%d",&t,&u);
        if(t==1){
            scanf("%d%d",&v,&k);k%=mod;
            update_path(u,v,k);
        }
        else if(t==3){
            scanf("%d",&k);k%=mod; 
            update_tree(u,k);
        }
        else if(t==2){
            scanf("%d",&v);
            printf("%lld\n",get_path(u,v)%mod);
        }
        else printf("%lld\n",get_tree(u)%mod);
    }
    return 0;
}

by Loser_Syx @ 2023-12-30 16:13:10

@Kniqht 您好,dfs2 函数中以根为起点的重链的 top 应该是根不是 1 捏。


by Kniqht @ 2023-12-30 17:13:33

@Loser_Syx 草,感谢您


by Kniqht @ 2023-12-30 17:13:46

复制粘贴导致的


|