洛谷P3384 【模板】树链剖分

20 篇文章 0 订阅
2 篇文章 0 订阅

题目
题解

#include<bits/stdc++.h>
using namespace std;
const int N=100002;
#define up(t) tr[t]=(tr[t<<1]+tr[t<<1|1])%M;
#define mid ((l+r)>>1)
struct node{
    int to,ne;
}e[N<<1];
int son[N],top[N],tr[N<<2],w[N],wt[N],id[N],la[N<<2],tot,h[N],fa[N],x,y,z,M,r,dep[N],n,siz[N],cnt,m,i,opt;
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
    int x=0,fl=1;char ch=gc();
    for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
    for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
    return x*fl;
}
inline void wri(int a){if(a>=10)wri(a/10);putchar(a%10|48);}
inline void wln(int a){if(a<0)a=-a,putchar('-');wri(a);puts("");}
void add(int x,int y){
    e[++tot]=(node){y,h[x]};
    h[x]=tot;
}
void build(int t,int l,int r){
    if (l==r){
        tr[t]=wt[l];
        return;
    }
    build(t<<1,l,mid);
    build(t<<1|1,mid+1,r);
    up(t);
}
void down(int t,int l,int r){
    if (la[t]){
        la[t<<1]+=la[t];
        la[t<<1|1]+=la[t];
        (tr[t<<1]+=(mid-l+1)*la[t])%=M;
        (tr[t<<1|1]+=(r-mid)*la[t])%=M;
        la[t]=0;
    }
}
void update(int t,int l,int r,int x,int y,int z){
    if (x<=l && r<=y){
        tr[t]+=z*(r-l+1);
        la[t]+=z;
        return;
    }
    down(t,l,r);
    if (x<=mid) update(t<<1,l,mid,x,y,z);
    if (mid<y) update(t<<1|1,mid+1,r,x,y,z);
    up(t);
}
int query(int t,int l,int r,int x,int y){
    if (x<=l && r<=y) return tr[t];
    down(t,l,r);
    int sum=0;
    if (x<=mid) sum+=query(t<<1,l,mid,x,y);
    if (mid<y) sum+=query(t<<1|1,mid+1,r,x,y);
    return sum%M;
}
void uprange(int x,int y,int z){
    z%=M;
    while (top[x]!=top[y]){
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        update(1,1,n,id[top[x]],id[x],z);
        x=fa[top[x]];
    }
    if (dep[x]>dep[y]) swap(x,y);
    update(1,1,n,id[x],id[y],z);
}
int qrange(int x,int y){
    int ans=0;
    while (top[x]!=top[y]){
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        (ans+=query(1,1,n,id[top[x]],id[x]))%=M;
        x=fa[top[x]];
    }
    if (dep[x]>dep[y]) swap(x,y);
    (ans+=query(1,1,n,id[x],id[y]))%=M;
    return ans;
}
void upson(int x,int z){
    update(1,1,n,id[x],id[x]+siz[x]-1,z);
}
int qson(int x){
    return query(1,1,n,id[x],id[x]+siz[x]-1);
}
void dfs1(int u,int f,int de){
    fa[u]=f;dep[u]=de;siz[u]=1;
    int mx=-1;
    for (int i=h[u],v;i;i=e[i].ne)
        if ((v=e[i].to)!=f){
            dfs1(v,u,de+1);
            siz[u]+=siz[v];
            if (siz[v]>mx) mx=siz[v],son[u]=v;
        }
}
void dfs2(int u,int topf){
    id[u]=++cnt;
    wt[cnt]=w[u];
    top[u]=topf;
    if (!son[u]) return;
    dfs2(son[u],topf);
    for (int i=h[u],v;i;i=e[i].ne)
        if ((v=e[i].to)!=fa[u] && v!=son[u]) dfs2(v,v);
}
int main(){
    n=read();m=read();r=read();M=read();
    for (i=1;i<=n;i++) w[i]=read();
    for (i=1;i<n;i++){
        x=read();y=read();
        add(x,y);add(y,x);
    }
    dfs1(r,0,1);
    dfs2(r,r);
    build(1,1,n);
    while (m--){
        opt=read();x=read();
        if (opt==1){
            y=read();z=read();
            uprange(x,y,z);
        }
        if (opt==2){
            y=read();
            wln(qrange(x,y));
        }
        if (opt==3){
            z=read();
            upson(x,z);
        }
        if (opt==4) wln(qson(x));
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值