P3384 【模板】轻重链剖分

题目链接:https://www.luogu.com.cn/problem/P3384

 

 

 

 

板子题(入门博客):https://www.cnblogs.com/ivanovcraft/p/9019090.html

 

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
typedef long long ll;

struct st{
    int to,next;
}stm[maxn*2];int head[maxn],cnt;
void add(int u,int v){
    stm[cnt].to=v;
    stm[cnt].next=head[u];
    head[u]=cnt++;
}
ll a[maxn],mod;
int tsize[maxn],tson[maxn],top[maxn],rk[maxn],id[maxn],dep[maxn],pre[maxn],co;
void init(int n){
    for(int i=1;i<=n;i++){
             head[i]=-1;
                tson[i]=0;
        }
        co=cnt=0;
}
struct trem{
    ll sum,lazy;
}tre[maxn<<2];
void dfs1(int now,int fa,int d){
    tsize[now]=1;
    pre[now]=fa;
    dep[now]=d;
//  cout<<now<<endl;
    for(int i=head[now];~i;i=stm[i].next){
        int to=stm[i].to;
        if(to==fa)continue;
        dfs1(to,now,d+1);
        tsize[now]+=tsize[to];
        if(tsize[to]>tsize[tson[now]])tson[now]=to;
    }
}
void dfs2(int now,int Top){
    rk[++co]=now;
    id[now]=co;//编号->dfs序
    top[now]=Top;
    if(tson[now]==0)return ;
    dfs2(tson[now],Top);
    for(int i=head[now];~i;i=stm[i].next){
        int to=stm[i].to;
        if(to==pre[now]||to==tson[now])continue;
        dfs2(to,to);
    }
}
void pushup(int rt){
    tre[rt].sum=(tre[rt<<1].sum+tre[rt<<1|1].sum)%mod;
    return ;
}
void pushdown(int rt,int l,int r){
    if(tre[rt].lazy){
        tre[rt<<1].lazy=(tre[rt<<1].lazy+tre[rt].lazy)%mod;
        tre[rt<<1|1].lazy=(tre[rt<<1|1].lazy+tre[rt].lazy)%mod;
        int mid=(l+r)/2;
        tre[rt<<1].sum=(tre[rt<<1].sum+tre[rt].lazy*(mid-l+1)%mod)%mod;
        tre[rt<<1|1].sum=(tre[rt<<1|1].sum+tre[rt].lazy*(r-mid)%mod)%mod;
        tre[rt].lazy=0;
    }
}
void build(int l,int r,int rt){
    if(l==r){
        tre[rt].sum=a[rk[l]];
        return ;
    }
    int mid=(l+r)/2;
    build(l,mid,rt*2);
    build(mid+1,r,rt*2+1);
    pushup(rt);
    return ;
}
ll query(int l,int r,int lm,int rm,int rt){
    if(l<=lm&&r>=rm){
        return tre[rt].sum;
    }
    ll ans=0;
    int mid=(lm+rm)/2;
    pushdown(rt,lm,rm);
    if(l<=mid)ans+=query(l,r,lm,mid,rt<<1);
    if(r>mid)ans+=query(l,r,mid+1,rm,rt<<1|1);
    return ans%mod;
}
void update(int l,int r,int lm,int rm,ll num,int rt){
    if(lm>=l&&rm<=r){
        tre[rt].lazy+=num;
        tre[rt].sum=(tre[rt].sum+1ll*(rm-lm+1)*num%mod)%mod;
        return ;
    }
    int mid=(lm+rm)/2;
    pushdown(rt,lm,rm);
    if(mid>=l)update(l,r,lm,mid,num,rt<<1);
    if(mid<r)update(l,r,mid+1,rm,num,rt<<1|1);
    pushup(rt);
}
void fun(int pos,int pos1,ll num,int n){
    int x=pos;
    int y=pos1;
    int f=top[x];
    int f1=top[y];
    while(f!=f1){
        if(dep[f]>=dep[f1]){
            update(id[f],id[x],1,n,num,1);
            x=pre[f];
            f=top[x];
        }
        else{
            update(id[f1],id[y],1,n,num,1);
            y=pre[f1];
            f1=top[y];
        }
    }
    if(id[x]<=id[y]){
        update(id[x],id[y],1,n,num,1);
    }
    else{
        update(id[y],id[x],1,n,num,1);
    }
    return ;
}
ll fun1(int pos,int pos1,int n){
    ll ans=0;
    int x=pos;
    int y=pos1;
    int f=top[x];
    int f1=top[y];
    while(f!=f1){    
        if(dep[f]>=dep[f1]){
            ans+=query(id[f],id[x],1,n,1);
            x=pre[f];
            f=top[x];
        }
        else{
            ans+=query(id[f1],id[y],1,n,1);
            y=pre[f1];
            f1=top[y];
        }
    }
    if(id[x]<=id[y]){
        ans+=query(id[x],id[y],1,n,1);
    }
    else{
        ans+=query(id[y],id[x],1,n,1);
    }
    return ans%mod;
}
int main(){
    int n,m,k;
    int u,v;
    scanf("%d%d%d%lld",&n,&m,&k,&mod);
    init(n);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
    }    
    dfs1(k,0,0);
    dfs2(k,k);
    build(1,n,1);
    int op,pos,pos1;
    ll num;
    for(int i=1;i<=m;i++){
        scanf("%d",&op);
        if(op==1){
            scanf("%d%d%lld",&pos,&pos1,&num);
            fun(pos,pos1,num,n);
        }
        else if(op==2){
            scanf("%d%d",&pos,&pos1);
            printf("%lld\n",fun1(pos,pos1,n));
        }
        else if(op==3){
            scanf("%d%lld",&pos,&num);
            update(id[pos],id[pos]+tsize[pos]-1,1,n,num,1);
        }
        else{
            scanf("%d",&pos);
            printf("%lld\n",query(id[pos],id[pos]+tsize[pos]-1,1,n,1));
        }
    }
    return 0;
}

 

 

 

 

posted @ 2020-04-19 21:24  风雨兼程-zhi  阅读(175)  评论(0编辑  收藏  举报