28pts求调,悬赏关注

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

TheIceStar @ 2023-07-03 12:07:46

#include <bits/stdc++.h>
#define ll long long
#define F(i,a,b) for (int i=a; i<=b; i++)
#define F1(i,a,b) for (int i=a; i<b; i++)
#define pb push_back
using namespace std;
const int MN=1e5+5;
struct segt{
    ll dat,add;
}tree[MN*4];
int N,M,R,P,size[MN],verw[MN],fa[MN],root,wson[MN],top[MN],dfn[MN],vistime,tnum,depth[MN],id[MN];
vector<int> G[MN];
void build(int p,int l,int r){
    if(l==r){tree[p].dat=verw[id[l]]; return ;}
    int mid=(l+r)>>1,A=p*2,B=p*2+1;
    build(A,l,mid);
    build(B,mid+1,r);
    tree[p].dat=tree[A].dat+tree[B].dat;
}
void pdown(int p,int l,int r){
    int mid=(l+r)>>1,A=p*2,B=p*2+1; 
    tree[A].add+=tree[p].add,tree[B].add+=tree[p].add;
    tree[A].dat+=tree[p].add*(mid-l+1), tree[B].dat+=tree[p].add*(r-mid);
    tree[A].dat%=P,tree[B].dat%=P;
    tree[A].add%=P,tree[B].add%=P;
    tree[p].add=0;
}
void change(int p,int l,int r,int cl,int cr,int cnum){
    if(cl<=l&&r<=cr){tree[p].dat+=(l-r+1)*cnum; tree[p].add+=cnum; return ;}
    int mid=(l+r)>>1,A=p*2,B=p*2+1;
    pdown(p,l,r);   
    if(cl<=mid) change(A,l,mid,cl,cr,cnum);
    if(cr>=mid+1) change(B,mid+1,r,cl,cr,cnum);
    tree[p].dat=(tree[A].dat+tree[B].dat)%P;    
}
ll ask(int p,int l,int r,int fl,int fr){
    if(fl<=l && r<=fr) return tree[p].dat;
    int mid=(l+r)>>1,A=p*2,B=p*2+1;
    pdown(p,l,r);
    ll res=0;
    if(fl<=mid) res+=ask(A,l,mid,fl,fr);
    if(fr>=mid+1) res+=ask(B,mid+1,r,fl,fr);
    return res%P;
}
void dfs1(int u){
    size[u]=1;
    depth[u]=depth[fa[u]]+1;
    for(auto v:G[u]) if(v!=fa[u]){
        fa[v]=u;
        dfs1(v);
        size[u]+=size[v];
        if(size[v]>size[wson[u]]) wson[u]=v;
    }   
}
void dfs2(int u,int frt){
    dfn[u]=++vistime;
    id[vistime]=u;
    top[u]=frt;
    if(wson[u]) dfs2(wson[u],frt);
    for(auto v:G[u]) if(v!=fa[u] && v!=wson[u]) dfs2(v,v);
}
void apath(int s,int t,int cnum){
    while(top[s]!=top[t]){
        if(depth[top[s]]<depth[top[t]]) swap(s,t);
        change(1,1,N,dfn[top[s]],dfn[s],cnum);
        s=fa[top[s]];
    }
    if(depth[s]>depth[t]) swap(s,t);
    change(1,1,N,dfn[s],dfn[t],cnum);
}
ll qpath(int s,int t){
    ll res=0;
    while(top[s]!=top[t]){
        if(depth[top[s]]<depth[top[t]]) swap(s,t);
        res=(ask(1,1,N,dfn[top[s]],dfn[s])+res)%P;
        s=fa[top[s]];
    }
    if(depth[s]>depth[t]) swap(s,t);
    res=(ask(1,1,N,dfn[s],dfn[t])+res)%P;
    return res;
}
void ason(int x,int cnum){
    change(1,1,N,dfn[x],dfn[x]+size[x]-1,cnum);
}
ll qson(int x){
    return ask(1,1,N,dfn[x],dfn[x]+size[x]-1)%P;
}
int main(){
//  freopen("qaq.in","r",stdin);
    cin>>N>>M>>R>>P;
    F(i,1,N) cin>>verw[i];
    F(i,1,N-1) {int u,v;cin>>u>>v;G[u].pb(v),G[v].pb(u);}
    dfs1(R);
    dfs2(R,R);
    build(1,1,N);
    F(i,1,M){
        int opt,x,y,z;
        cin>>opt;
        if(opt==1){
            cin>>x>>y>>z;
            apath(x,y,z);
        } else if (opt==2){
            cin>>x>>y;
            cout<<qpath(x,y)<<endl;
        } else if(opt==3){
            cin>>x>>z;
            ason(x,z);
        } else if(opt==4){
            cin>>x;
            cout<<qson(x)<<endl;
        }
    }
    return 0;
}

错误数据

8 10 6 623232
56 838 680 614 846 408 890 829 
1 2
2 3
3 4
1 5
4 7
4 8
7 6
3 4 859
1 4 2 189
2 1 7

悬赏关注两个 谢谢大佬了


by Anli_li_father @ 2023-07-03 13:34:18

你change函数里第一行

tree[p].dat+=(l-r+1)*cnum

应该改为

tree[p].dat+=(r-l+1)*cnum

by TheIceStar @ 2023-07-03 16:46:13

Ohhh 谢谢,orz 抱歉现在才看到


by TheIceStar @ 2023-07-03 16:46:58

已关注


|