Mnzn树链剖分调了有一个小时求助QAQ

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

mzycの喰种 @ 2023-07-12 20:50:27

#include<bits/stdc++.h>
using namespace std;
#define N 2*114514
#define M 1919810
#define ll long long
#define ls now<<1
#define rs now<<1|1
#define INF 1145141919810
ll n,a,b,c,w[N],q,root,mod;
ll opt;
struct xx{
    ll next,to,val;
}e[2*N];
ll head[2*N],cnt;
void add(ll x,ll y){
    e[++cnt].next=head[x];
    e[cnt].to=y;
    head[x]=cnt;
}
struct tree{
    ll l,r;
    ll sum,add;
    ll len;
}t[4*N];
ll f[N],dept[N],size[N],son[N];
//父节点/深度/字数大小/重儿子 
void dfs1(ll u,ll dep){ //处理出每个点的信息 
    size[u]=1;
    dept[u]=dep;
    for(int i=head[u];i;i=e[i].next){
        ll v=e[i].to;
        if(v==f[u]) continue;
        f[v]=u;
        dfs1(v,dep+1);
        size[u]+=size[v];
        if(size[v]>size[son[u]]) son[u]=v;
    }
}
ll top[N],dfn[N],rk[N],t_cnt; //记录重链,dfs序,重链节点对应点编号 
void dfs2(ll u,ll t){ //t为重链顶端 
    top[u]=t;
    dfn[u]=++t_cnt;
    rk[t_cnt]=u;
    if(!son[u]) return;
    dfs2(son[u],t);
    for(int i=head[u];i;i=e[i].next){
        ll v=e[i].to;
        if(v!=son[u]&&v!=f[u]) dfs2(v,v); //位于轻链底端则top为他本身
    }
}
void pushup(ll now){
    t[now].sum=t[ls].sum+t[rs].sum;
    t[now].sum%=mod;
}
void pushdown(ll now){
    t[ls].add+=t[now].add;
    t[ls].sum+=t[now].add*t[now].len;
    t[rs].add+=t[now].add;
    t[rs].sum+=t[now].add*t[now].len;
    t[now].add=0;
}
void build(ll now,ll l,ll r){
    t[now].l=l,t[now].r=r;
    t[now].len=r-l+1,t[now].add=0;
    if(l==r){
        t[now].sum=w[rk[l]];
        return;
    }
    ll mid=l+r>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    pushup(now);
}
void update(ll now,ll x,ll y,ll k){
    if(t[now].l>=x&&t[now].r<=y){
        t[now].add+=k;
        t[now].sum+=t[now].len*k;
        t[now].sum%=mod;
        return;
    }
    pushdown(now);
    ll mid=t[now].l+t[now].r>>1;
    if(x<=mid) update(ls,x,y,k);
    if(y>mid) update(rs,x,y,k);
    pushup(now);
}
void update_side(ll u,ll v,ll k){
    k%=mod;
    while(top[u]!=top[v]){
        if(dept[top[u]]<=dept[top[v]]) swap(u,v);
        update(1,dfn[top[u]],dfn[u],k);
        u=f[top[u]];
    }
    if(dept[u]<dept[v]) swap(u,v);
    update(1,dfn[u],dfn[v],k);
}
void update_son(ll x,ll k){
    update(1,dfn[x],dfn[x]+size[x]-1,k);
}
ll qsum(ll now,ll x,ll y){
    if(t[now].l>=x&&t[now].r<=y) return t[now].sum;
    ll mid=t[now].l+t[now].r>>1,ans=0;
    pushdown(now);
    if(x<=mid) ans+=qsum(ls,x,y),ans%=mod;
    if(y>mid) ans+=qsum(rs,x,y),ans%=mod;
    pushup(now);
    return ans;
}
ll QSUM(ll u,ll v){
    ll ans=0;
    while(top[u]!=top[v]){ //LCA 
        if(dept[top[u]]<dept[top[v]]) swap(u,v);
        ans+=qsum(1,dfn[top[u]],dfn[u]);
        ans%=mod;
        u=f[top[u]];
    }
    if(dept[u]<dept[v]) swap(u,v);
    ans+=qsum(1,dfn[v],dfn[u]);
    return ans;
}
ll QSON(ll x){
    return qsum(1,dfn[x],dfn[x]+size[x]-1)%mod; //注意
}
int main(){
    //ios::sync_with_stdio(0);
    //cin.tie(0); cout.tie(0);
    cin>>n>>q>>root>>mod;
    for(int i=1;i<=n;++i) cin>>w[i];
    for(int i=1;i<n;++i){
        cin>>a>>b;
        add(a,b);
        add(b,a);
    }
    dfs1(root,0); dfs2(root,root);
    build(1,1,n);
    //for(int i=1;i<=4*n;++i) cout<<t[i].len<<" "; cout<<'\n';
    while(q--){
        cin>>opt;
        if(opt==1) cin>>a>>b>>c,update_side(a,b,c);
        if(opt==2) cin>>a>>b,cout<<QSUM(a,b)%mod<<'\n';
        if(opt==3) cin>>a>>b,update_son(a,b);
        if(opt==4) cin>>a,cout<<QSON(a)%mod<<'\n'; 
        //for(int i=1;i<=4*n;++i) cout<<t[i].sum<<'\n';
    }
    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 mzycの喰种 @ 2023-07-12 20:56:24

救救萌新


by Zzzcr @ 2023-07-12 21:03:09

pushdown写错了,还有query不需要pushup

void pushdown(ll now)
{
    t[ls].add += t[now].add;
    t[ls].sum += t[now].add * t[ls].len;
    t[rs].add += t[now].add;
    t[rs].sum += t[now].add * t[rs].len;
    t[now].add = 0;
}

by mzycの喰种 @ 2023-07-12 21:05:28

@Zzzcr 哦哦,谢谢大佬,还有pushup应该多加了没影响吧


by mzycの喰种 @ 2023-07-12 21:08:12

az,还是WA 28pts


by mzycの喰种 @ 2023-07-12 21:14:50

已过,update_side里面一个大于写成了小于,警钟长鸣……


|