P3384 【模板】树链剖分

P3384 【模板】树链剖分

在这里插入图片描述

模型总结

树链剖分

关键点

  1. if(dep[top[x]]<dep[top[y]]) swap(x,y);而不是 if(dep[x]<dep[y]) swap(x,y);否则会重复统计
  2. 开始不要忘记 top[rt]=rt;
  3. 建双向边,邻接表存边时数组大小要*2
#include<iostream>
#include<cstdio>
#define lc (cur<<1)
#define rc (cur<<1|1)
#define mid ((p[cur].l+p[cur].r)>>1)
#define ll long long
using namespace std;
ll read(){
    ll x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return f*x;
}
const int maxn=4e5+5;

int n,m;
ll mod,a[maxn];
int h[maxn],nxt[maxn<<1],to[maxn<<1],tot,rt;
void ade(int x,int y){
    to[++tot]=y; nxt[tot]=h[x]; h[x]=tot;
}
int fa[maxn],siz[maxn],son[maxn],newp[maxn],oldp[maxn],dep[maxn];
int dfn,top[maxn];
void dfs1(int f,int u){
    fa[u]=f;
    dep[u]=dep[f]+1;
    siz[u]=1;
    for(int i=h[u];i;i=nxt[i]){
        int v=to[i];
        if(v==f)continue;
        dfs1(u,v);
        if(siz[v]>siz[son[u]]) son[u]=v;
        siz[u]+=siz[v];
    }
}
void dfs2(int f,int u){
    oldp[newp[u]=++dfn]=u;
    if(son[u]){
        top[son[u]]=top[u];
        dfs2(u,son[u]);
    }
    for(int i=h[u];i;i=nxt[i]){
        int v=to[i];
        if(v==f||son[u]==v)continue;
        top[v]=v;
        dfs2(u,v);
    }
}
struct node{
    int l,r;
    ll val,tag;
    node(){val=tag=0;}
}p[maxn];
void updata(int cur){
    p[cur].val=(p[lc].val+p[rc].val)%mod;
}
void build(int cur,int l,int r){
    p[cur].l=l; p[cur].r=r;
    if(l==r){
        p[cur].val=a[oldp[l]];
        return;
    }
    build(lc,l,mid);
    build(rc,mid+1,r);
    updata(cur);
}
void add(int cur,ll v){
    v%=mod;
    p[cur].tag=(p[cur].tag+v)%mod;
    p[cur].val=(p[cur].val+1ll*(p[cur].r-p[cur].l+1)%mod*v%mod)%mod;
}
void pushdown(int cur){
    if(p[cur].tag){
        add(lc,p[cur].tag);
        add(rc,p[cur].tag);
        p[cur].tag=0;
    }
}
void upd(int cur,int l,int r,ll v){
    if(p[cur].l>=l&&p[cur].r<=r){
        add(cur,v); return;
    }
    pushdown(cur);
    if(p[lc].r>=l) upd(lc,l,r,v);
    if(p[rc].l<=r) upd(rc,l,r,v);
    updata(cur);
}
ll qry(int cur,int l,int r){
    if(p[cur].l>=l&&p[cur].r<=r){
        return p[cur].val;
    }
    pushdown(cur);
    ll ans=0;
    if(p[lc].r>=l) ans=(ans+qry(lc,l,r))%mod;
    if(p[rc].l<=r) ans=(ans+qry(rc,l,r))%mod;
    return ans%mod;
}
int main(){
    //freopen("c.in","r",stdin);
    n=read(); m=read();  rt=read();mod=read();
    for(int i=1;i<=n;i++){
        a[i]=read(); a[i]%=mod;
    }
    for(int i=1;i<n;i++){
        int x=read(),y=read();
        ade(x,y); ade(y,x);
    }
    top[rt]=rt;
    dfs1(0,rt);
    dfs2(0,rt);
    build(1,1,n);
    for(int i=1;i<=m;i++){
        int op=read();
        if(op==1){
            int x=read(),y=read();
            ll z=read();
            z%=mod;
            while(top[x]!=top[y]){
                if(dep[top[x]]<dep[top[y]]) swap(x,y);
                upd(1,newp[top[x]],newp[x],z);
                x=fa[top[x]];
            }
            if(dep[x]<dep[y]) swap(x,y);
            upd(1,newp[y],newp[x],z);
        }
        if(op==2){
            int x=read(),y=read();
            ll ans=0;
            while(top[x]!=top[y]){
                if(dep[top[x]]<dep[top[y]]) swap(x,y);
                ans=(ans+qry(1,newp[top[x]],newp[x]))%mod;
                x=fa[top[x]];
            }
            if(dep[x]<dep[y]) swap(x,y);
            printf("%lld\n",(ans+qry(1,newp[y],newp[x]))%mod);
        }
        if(op==3){
            int x=read();
            ll z=read();
            z%=mod;
            upd(1,newp[x],newp[x]+siz[x]-1,z);
        }
        if(op==4){
            int x=read();
            printf("%lld\n",qry(1,newp[x],newp[x]+siz[x]-1)%mod);
        }
    }
    return 0;
} 

springboot052基于Springboot+Vue旅游管理系统毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值