求调错(除134WA)

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

AfterFullStop @ 2023-01-31 16:20:05

找到眼瞎都没找出来

#include<bits/stdc++.h>
#define ll long long
#define int long long
#define ri register int
#define maxn 500005
using namespace std;
inline ll read(){
    ll x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=x*10+ch-48;
        ch=getchar();
    }
    return x*f;
}
inline void write(ll n){
    if(n<0){
        putchar('-');
        n=-n;
    }
    if(n>9)
        write(n/10);
    putchar(n%10+'0');
}
ll n,m,r,p;
ll a[maxn],b[maxn];
int cnt,head[maxn],to[maxn],nxt[maxn];
int siz[maxn],dep[maxn],fa[maxn],son[maxn],top[maxn],id[maxn];
//线段树部分
struct tn{
    int l,r;
    ll s,lazy;
}tree[maxn<<2];
void build(int i,int l,int r){
    tree[i].l=l;tree[i].r=r;
    if(l==r){
        tree[i].s=b[l];
        return;
    }
    int mid=l+r>>1;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    tree[i].s=tree[i<<1].s+tree[i<<1|1].s;
    tree[i].s%=p;
}
inline void push(int i){
    if(tree[i].lazy){
        tree[i<<1].lazy+=tree[i].lazy;
        tree[i<<1].s+=tree[i].lazy*(tree[i<<1].r-tree[i<<1].l+1)%p;
        tree[i<<1|1].lazy+=tree[i].lazy;
        tree[i<<1|1].s+=tree[i].lazy*(tree[i<<1|1].r-tree[i<<1|1].l+1)%p;
        tree[i<<1].s%=p;
        tree[i<<1|1].s%=p;
        tree[i<<1].lazy%=p;
        tree[i<<1|1].lazy%=p;
        tree[i].lazy=0;
    }
}
inline void change(int i,int l,int r,ll d){
    if(tree[i].l>=l&&tree[i].r<=r){
        tree[i].lazy=(tree[i].lazy+d)%p;
        tree[i].s=(tree[i].s+d*(tree[i].r-tree[i].l+1)%p)%p;
        return;
    }push(i);
    int mid=(tree[i].l+tree[i].r)>>1;
    if(l<=mid)change(i<<1,l,r,d);
    if(r>mid)change(i<<1|1,l,r,d);
    tree[i].s=(tree[i<<1].s+tree[i<<1|1].s)%p;
}
inline ll query(int i,int l,int r){
    if(tree[i].l>=l&&tree[i].r<=r)
        return tree[i].s%p;
    push(i);
    int mid=(tree[i].l+tree[i].r)>>1;
    ll val=0;
    if(l<=mid)val=(val+query(i<<1,l,r))%p;
    if(r>mid)val=(val+query(i<<1|1,l,r))%p;
    return val%p;
}
//线段树部分结束
inline void add(int u,int v){
    ++cnt;
    to[cnt]=v;
    nxt[cnt]=head[u];
    head[u]=cnt;
}
void dfs1(int u){
    int ms=0;
    siz[u]=1;
    for(ri e=head[u];e;e=nxt[e]){
        int v=to[e];
        if(v==fa[u])continue;
        fa[v]=u;
        dep[v]=dep[u]+1;
        dfs1(v);
        siz[u]+=siz[v];
        if(siz[v]>ms){
            ms=siz[v];
            son[u]=v;
        }
    }
}
int tot=0;
void dfs2(int u,int topf){
    id[u]=++tot;
    b[id[u]]=a[u];
    top[u]=topf;
    if(son[u])dfs2(son[u],topf);
    for(ri e=head[u];e;e=nxt[e]){
        int v=to[e];
        if(v!=fa[u]&&v!=son[u])dfs2(v,v);
    }
}
inline void uRange(int x,int y,ll z){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        change(1,id[x],id[top[x]],z);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    change(1,id[x],id[y],z);
}
inline ll qRange(int x,int y){
    ll ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        ans=(ans+query(1,id[x],id[top[x]]))%p;
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    return (ans+query(1,id[x],id[y]))%p;
}
inline void uTree(int u,ll k){
    change(1,id[u],id[u]+siz[u]-1,k);
}
inline ll qTree(int u){
    return query(1,id[u],id[u]+siz[u]-1);
}
int op,x,y,z;
signed main(){
    n=read();m=read();r=read();p=read();
    for(ri i=1;i<=n;i++)a[i]=read()%p;
    for(ri i=1,u,v;i<n;i++){
        u=read();v=read();
        add(u,v);add(v,u);
    }
    dfs1(r);
    dfs2(r,r);
    build(1,1,n);
    while(m--){
        op=read();
        if(op==1){
            x=read();y=read();z=read();
            uRange(x,y,z);
        }if(op==2){
            x=read();y=read();
            write(qRange(x,y));printf("\n");
        }if(op==3){
            x=read();y=read();
            uTree(x,y);
        }if(op==4){
            x=read();
            write(qTree(x));printf("\n");
        }
    }
    return 0;
}

by smallpeter @ 2023-01-31 16:54:01

@LemonAndMelon 树剖过程中错了


by smallpeter @ 2023-01-31 16:54:53

inline void uRange(int x,int y,ll z){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        change(1,id[x],id[top[x]],z);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    change(1,id[x],id[y],z);
}
inline ll qRange(int x,int y){
    ll ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        ans=(ans+query(1,id[x],id[top[x]]))%p;
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    return (ans+query(1,id[x],id[y]))%p;
}

里面while循环的query的id[x]和id[top[x]]写反了


by smallpeter @ 2023-01-31 16:56:20

top[x]是x的祖先,那dfs序肯定是top[x]要小


by AfterFullStop @ 2023-01-31 17:00:26

@small_peter 傻了,已AC,感谢


|