树剖加线段树37分,实在是找不到哪里错了,求助

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

lmz20050701 @ 2024-05-29 21:30:59

#include<bits/stdc++.h>
#define ll unsigned long long
using namespace std;
const ll N=1e6+10;
ll n,m,r,M;
ll a[N];
vector<ll> edge[N];
ll fa[N],deep[N],siz[N],top[N],to[N],from[N],son[N],dfn[N];
ll cnt=0;
void dfs1(ll x,ll f)
{
    siz[x]=1;
    fa[x]=f;
    deep[x]=deep[f]+1;
    for(ll i=0;i<edge[x].size();i++)
    {
        ll t=edge[x][i];
        if(t==f) continue;
        dfs1(t,x);
        siz[x]+=siz[t];
        if(siz[son[x]]<siz[t]) son[x]=t;
    }
}
void dfs2(ll x,ll f,ll tp)
{
    cnt++;
    to[x]=cnt;
    from[cnt]=x;
    top[x]=tp;
    if(son[x]) dfs2(son[x],x,tp);
    for(ll i=0;i<edge[x].size();i++)
    {
        ll t=edge[x][i];
        if(t==f) continue;
        if(t==son[x]) continue;
        dfs2(t,x,t);
    }
    dfn[x]=cnt;
}
ll tree[N*4];
ll lazy[N*4];
void pushup(ll p,ll l,ll r)
{
    tree[p]=tree[p*2]+tree[p*2+1];
    tree[p]%=M;tree[p*2]%=M;tree[p*2+1]%=M;
}
void pushdown(ll p,ll l,ll r)
{
    ll mid=(l+r)/2;
    lazy[p*2]+=lazy[p];   lazy[p*2+1]+=lazy[p];
    tree[p*2]+=lazy[p]*(mid-l+1);
    tree[p*2+1]+=lazy[p]*(r-mid);
    lazy[p]=0;
    pushup(p,l,r);
}
void build(ll p,ll l,ll r)
{
    if(l==r)
    {
        tree[p]=a[from[l]]%M;
        return ;
    }
    ll mid=(l+r)/2;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    pushup(p,l,r);
}
void add1(ll p,ll l,ll r,ll x,ll z)  //单点
{
    if(l==r)
    {
        tree[p]+=z;
        tree[p]%=M;
        return ;
    }
    if(lazy[p]) pushdown(p,l,r);
    ll mid=(l+r)/2;
    if(x<=mid) add1(p*2,l,mid,x,z);
    else add1(p*2+1,mid+1,r,x,z);
    pushup(p,l,r);
}
void add2(ll p,ll l,ll r,ll x,ll y,ll z)
{
    if(x<=l&&r<=y)
    {
        tree[p]+=z*(r-l+1);
        lazy[p]+=z;
        tree[p]%=M;
        return ;
    }
    if(lazy[p]) pushdown(p,l,r);
    ll mid=(l+r)/2;
    if(x<=mid) add2(p*2,l,mid,x,y,z);
    if(y>=mid+1) add2(p*2+1,mid+1,r,x,y,z);
    pushup(p,l,r);
}
ll cala(ll p,ll l,ll r,ll x,ll y)
{
    if(x<=l&&r<=y)
    {
        return tree[p];
    }
    if(lazy[p]) pushdown(p,l,r);
    ll mid=(l+r)/2;
    ll ans=0;
    if(x<=mid) ans+=cala(p*2,l,mid,x,y);
    if(y>=mid+1) ans+=cala(p*2+1,mid+1,r,x,y);
    return ans%M;
}
void add_lca(ll x,ll y,ll z)
{
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        add2(1,1,n,to[x],to[top[x]],z);
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    add2(1,1,n,to[x],to[y],z);
}
ll cala_lca(ll x,ll y)
{
    ll ans=0;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        ans+=cala(1,1,n,to[x],to[top[x]]);
        ans%=M;
        x=fa[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    ans+=cala(1,1,n,to[x],to[y]);
    return ans%M;
}
int main()
{
    cin>>n>>m>>r>>M;
    for(ll i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    for(ll i=1;i<n;i++)
    {
        ll x,y;
        cin>>x>>y;
        edge[x].push_back(y);
        edge[y].push_back(x);
    }
    dfs1(r,0);
    dfs2(r,0,r);
    build(1,1,n);
    for(ll i=1;i<=m;i++)
    {
        ll opt;
        cin>>opt;
        if(opt==1)
        {
            ll x,y,z;
            cin>>x>>y>>z;
            add_lca(x,y,z);
        }
        else if(opt==2)
        {
            ll x,y;
            cin>>x>>y;
            cout<<cala_lca(x,y)<<endl;
        }
        else if(opt==3)
        {
            ll x,z;
            cin>>x>>z;
            add2(1,1,n,to[x],dfn[x],z);
        }
        else if(opt==4)
        {
            ll x;
            cin>>x;
            cout<<cala(1,1,n,to[x],dfn[x])<<endl;
        }
    }
    return 0;
}
/*
5 5 2 24
7 3 7 8 0 
1 2
1 5
3 1
4 1
3 4 2
3 2 2
4 5
1 5 1 3
2 1 3
*/

by AllenJYL @ 2024-05-29 21:49:34

pushdown 里面 tree[] 未取模


by lmz20050701 @ 2024-05-29 22:25:49


void pushdown(ll p,ll l,ll r)
{
    ll mid=(l+r)/2;
    lazy[p*2]+=lazy[p];   lazy[p*2+1]+=lazy[p];
    tree[p*2]+=((lazy[p]%M)*((mid-l+1)%M))%M;
    tree[p*2+1]+=((lazy[p]%M)*((r-mid)%M))%M;
    tree[p]%=M; tree[p*2]%=M; tree[p*2+1]%=M;
    lazy[p]=0;
    pushup(p,l,r);
}
改成这样还是37呀```
@[AllenJYL](/user/459170)

by AllenJYL @ 2024-05-30 17:45:26

add_lca()add2(1,1,n,to[x],to[top[x]],z); 应修改为 add2(1,1,n,to[top[x]],to[x],z);

cala_lca()ans+=cala(1,1,n,to[x],to[top[x]]); 应修改为 ans+=cala(1,1,n,to[top[x]],to[x]);


by lmz20050701 @ 2024-05-30 23:04:30

ac了 感谢大佬 @AllenJYL


by lmz20050701 @ 2024-05-30 23:05:18

此贴解


|