求助上面28分,下面RE

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

UQAQU @ 2024-08-01 22:40:34

#include<bits/stdc++.h>
#define ll long long int 
using namespace std;
const ll N=5000007;
ll n,m,r,mod;
struct tree{
    ll next,to,w;
}edge[2*N];
ll head[N],top[N],father[N],son[N],cnt;
ll val[N],num[N],id[N],size[N],deep[N],number;
ll d[4*N],lazy[N*4];
inline ll read(){
    ll ans=0,res=1;
    char c;
    while (c<'0' || c>'9'){
        if (c=='-'){
            res=-1;
        }
        c=getchar();
    }
    while (c>='0' && c<='9'){
        ans=(ans<<3)+(ans<<1)+(c^48);
        c=getchar();
    }
    return ans*res;
}
void add_edge(ll u,ll v){
    cnt++,edge[cnt].to=v,edge[cnt].next=head[u],head[u]=cnt;
}
void dfs1(ll u,ll v){
    deep[u]=deep[v]+1;
    father[u]=v;
    size[u]=1;
    for (ll i=head[u];i!=0;i=edge[i].next){
        ll j=edge[i].to;
        if (j==v){
            continue;
        }
        dfs1(j,u);
        size[u]+=size[j];
        if (size[j]>size[son[u]]){
            son[u]=j;
        }
    }
}
void dfs2(ll u,ll tp){
    number++;
    id[u]=number;
    val[number]=u;
    top[u]=tp;
    if (!son[u]){
        return ;
    }
    dfs2(son[u],tp);
    for (ll i=head[u];i!=0;i=edge[i].next){
        ll j=edge[i].to;
        if (j==son[u] || j==father[u]){
            continue;
        }
        dfs2(j,j);
    }
}
void build(ll l,ll r,ll p){
    if (l==r){
        d[p]=num[val[l]];
        return ;
    }
    ll mid=l+((r-l)>>1);
    build(l,mid,2*p),build(mid+1,r,2*p+1);
    d[p]+=d[2*p]+d[p*2+1];
    d[p]%=mod;
    return ;
}
ll query(ll l,ll r,ll s,ll t,ll p){
    if (l<=s && t<=r){
        return d[p]%mod;
    }
    if (s>r || t<l){
        return 0;
    }
    ll mid=s+((t-s)>>1);
    if (lazy[p]!=0){
        d[p*2]+=lazy[p]*(mid-s+1),d[p*2+1]+=lazy[p]*(t-mid);
        d[p*2]%=mod,d[p*2+1]%=mod;
        lazy[p*2]+=lazy[p],lazy[p*2+1]+=lazy[p],lazy[2*p]%=mod,lazy[2*p+1]%=mod;
        lazy[p]=0;
    }
    ll ans=0;
    if (l<=mid){
        ans+=query(l,r,s,mid,p*2);
        ans%=mod;
    }
    if (r>mid){
        ans+=query(l,r,mid+1,t,2*p+1);
        ans%=mod;
    }
    return ans%=mod;
}
ll query_sum(ll u,ll v){
    ll res=0;
    while(top[u]!=top[v]){
        if (deep[top[u]]<deep[top[v]]){
            swap(u,v);
        }
        res+=query(id[top[u]],id[u],1,number,1);
        u=father[top[u]];
        res%=mod;
    }
    if (deep[u]<deep[v]){
        swap(u,v);
    } 
    res+=query(id[v],id[u],1,number,1);
    res%=mod;
    return res%mod;
}
ll query_tree(ll u){
    return query(id[u],id[u]+size[u]-1,1,number,1);
}
void update(ll l,ll r,ll s,ll t,ll k,ll p){
    if (l<=s && t<=r){
        d[p]+=(t-s+1)*k,lazy[p]+=k;
        d[p]%=mod;
        lazy[p]%=mod;
        return ;
    }
    if (s>r || t<l){
        return ;
    }
    ll mid=s+((t-s)>>1);
    if (lazy[p]!=0 && s!=t){
        d[2*p]+=lazy[p]*(mid-s+1),d[p*2+1]+=lazy[p]*(t-mid);
        d[p*2]%=mod,d[p*2+1]%=mod;
        lazy[p*2]+=lazy[p],lazy[p*2+1]+=lazy[p];
        lazy[p*2]%=mod,lazy[p*2+1]%=mod;
        lazy[p]=0;
    }
    if (l<=mid){
        update(l,r,s,mid,k,2*p);
    }
    if (r>mid){
        update(l,r,mid+1,t,k,2*p+1);
    }
    d[p]=d[p*2]+d[p*2+1];
    d[p]%=mod;
}
void update_path(ll u,ll v,ll k){
    while(top[u]!=top[v]){
        if (deep[u]<deep[v]){
            swap(u,v);
        }
        update(id[top[u]],id[u],1,number,k,1);
        u=father[top[u]];
    }
    if (deep[u]<deep[v]){
        swap(u,v);
    }
    update(id[v],id[u],1,number,k,1);
}
void update_tree(ll u,ll k){
    update(id[u],id[u]+size[u]-1,1,number,k,1);
}
int main()
{
    n=read(),m=read(),r=read(),mod=read();
    for (ll i=1;i<=n;i++){
        num[i]=read();
        num[i]%=mod;
    }
    for (ll i=1;i<=n-1;i++){
        ll x,y;
        x=read(),y=read();
        add_edge(x,y);
        add_edge(y,x);
    }
    dfs1(r,0);
    dfs2(r,r);
    build(1,n,1);
    while (m--){
        ll t,x,y,z;
        t=read();
        if (t==1){
            x=read(),y=read(),z=read();
            update_path(x,y,z);
        }
        if (t==2){
            x=read(),y=read();
            cout<<query_sum(x,y)%mod<<endl;
        }
        if (t==3){
            x=read(),z=read();
            update_tree(x,z);
        }
        if (t==4){
            x=read();
            cout<<query_tree(x)%mod<<endl;
        }
    }
    return 0;
}
#include<bits/stdc++.h>
#define ll long long int
const int N=5e6+7;
using namespace std;
struct tree{
    int to,next,w;
}edge[2*N];
int n,m,r,mod;
int head[N],cnt,deep[N],sum[N],ch[N];
int top[N],fa[N],son[N],number,size[N],val[N],lazy[N],id[N];
void add_edge(int u,int v){
    cnt++;
    edge[cnt].to=v,edge[cnt].next=head[u],head[u]=cnt;
}
void dfs1(int u,int v){
    deep[u]=deep[v]+1;
    fa[u]=v;
    size[u]=1;
    for (int i=head[u];i!=0;i=edge[i].next){
        int j=edge[i].to;
        if (j==v){
            continue;
        }
        dfs1(j,u);
        size[u]+=size[j];
        if (size[j]>size[son[u]]){
            son[u]=j;
        }
    }
}
void dfs2(int u,int v){
    number++;
    id[u]=number,val[number]=u,top[u]=v;
    if (!son[u]){
        return ;
    }
    dfs2(son[u],v);
    for (int i=head[u];i!=0;i=edge[i].next){
        int j=edge[i].to;
        if (j!=fa[u] && j!=son[u]){
            dfs2(j,j);
        }
    }
    return ;
}
void build(int u,int l,int r){
    if (l==r){
        sum[u]=ch[val[l]];
        return ;
    }
    int mid=(l+r)>>1;
    build(2*u,l,mid);
    build(2*u+1,mid+1,r);
    sum[u]+=sum[2*u]+sum[2*u+1];
    sum[u]%=mod;
    return ;
}
void push(int u,int l,int r){
    int mid=(l+r)>>1;
    lazy[2*u]+=lazy[u];lazy[2*u]%=mod;
    lazy[2*u+1]+=lazy[u];lazy[2*u+1]%=mod;
    sum[2*u]+=lazy[u]*(mid-l+1);sum[2*u]%=mod;
    sum[2*u+1]+=lazy[u]*(r-mid);sum[2*u]%=mod;
    lazy[u]=0;
    return ;
}
void update(int u,int s,int t,int l,int r,int k){
    if (l<=s && r>=t){
        sum[u]+=k*(t-s+1);sum[u]%=mod;
        lazy[u]+=k;lazy[u]%=mod;
        return ;
    }
    if(s>r||t<l)return ;
    int mid=(s+t)>>1;
    if (lazy[u]!=0){
        push(u,s,t);
    }
    if (l>=mid){
        update(2*u,s,mid,l,r,k);
    }
    if (r>mid){
        update(2*u+1,mid+1,t,l,r,k);
    }
    sum[u]=(sum[2*u]+sum[2*u+1])%mod;
    return ;
}
ll query(int u,int s,int t,int l,int r){
    if (l<=s && r>=t){
        return sum[u]%=mod;
    }
    if(s>r|| t<l) return 0;
    int mid=(s+t)>>1;
    ll ans=0;
    if (mid>=l){
        ans+=query(2*u,s,mid,l,r);
        ans%=mod;
    }
    if (r>mid){
        ans+=query(2*u+1,mid+1,t,l,r);
        ans%=mod;
    }
    return ans%=mod;
}
ll query_sum(int u,int v){
    ll ans=0;
    while (top[u]!=top[v]){
        if (deep[top[u]]<deep[top[v]]){
            swap(u,v);
        }
        ans+=query(1,1,number,id[top[u]],id[u]);
        u=fa[top[u]];
    }
    if (id[u]<id[v]){
        swap(u,v);
    }
    ans+=query(1,1,number,id[v],id[u]);
    return ans;
}
void update_path(int u,int v,int k){
    while (top[u]!=top[v]){
        if (deep[u]<deep[v]){
            swap(u,v);
        }
        update(1,1,number,id[top[u]],id[u],k);
        u=fa[top[u]];
    }
    if (id[u]<id[v]){
        swap(u,v);
    }
    update(1,1,number,id[v],id[u],k);
}
int main()
{
    int n,m,r,mod;
    cin>>n>>m>>r>>mod;
    for (int i=1;i<=n;i++){
        cin>>ch[i];
    }
    for (int i=1;i<=n-1;i++){
        int x,y;
        cin>>x>>y;
        add_edge(x,y),add_edge(y,x);
    }
    dfs1(r,0);
    dfs2(r,r);
    build(1,1,n);
    while (m--){
        int t,x,y,z;
        cin>>t;
        if (t==1){
            cin>>x>>y>>z;
            update_path(x,y,z%mod);
        }
        if (t==2){
            cin>>x>>y;
            cout<<query_sum(x,y)%mod<<endl;
        }
        if (t==3){
            cin>>x>>y;
            update(1,1,n,id[x],id[x]+size[x]-1,y%mod);
        }
        if (t==4){
            cin>>x;
            cout<<query(1,1,n,id[x],size[x]+id[x]-1)%mod<<endl;
        }
    }
    return 0;
}

|