树链剖分模板

Posted acm1ruoji

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树链剖分模板相关的知识,希望对你有一定的参考价值。

题目链接:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define pb push_back
#define fi first
#define se second
const int N=1e6+10;
const int mod7=1e9+7;
void read(int &a)
{
    a=0;int d=1;char ch;
    while(ch=getchar(),ch>9||ch<0)
        if(ch==-)
            d=-1;
    a=ch^48;
    while(ch=getchar(),ch>=0&&ch<=9)
        a=(a<<3)+(a<<1)+(ch^48);
    a*=d;
}
vector <int> v[N];
int siz[N],dep[N],f[N],son[N],top[N],id[N],rk[N],cnt,val[N];
int n,m,root,mod;
struct note{int l,r,sum,lazy;}tree[N<<1];
void dfs1(int x)
{
    siz[x]=1,dep[x]=dep[f[x]]+1;
    for(auto i:v[x])
    {
        if(i!=f[x])
        {
            f[i]=x;dfs1(i),siz[x]+=siz[i];
            if(siz[son[x]]<siz[i]) son[x]=i;
        }
    }
}
void dfs2(int x,int tp)
{
    top[x]=tp,id[x]=++cnt,rk[cnt]=x;
    if(son[x]) dfs2(son[x],tp);
    for(auto i:v[x]) if(i!=f[x]&&i!=son[x]) dfs2(i,i);
}
void work(int now,int k)
{
    (tree[now].sum+=1ll*(tree[now].r-tree[now].l+1)*k%mod)%=mod;
    tree[now].lazy+=k;
}
void pushdown(int now)
{
    work(now<<1,tree[now].lazy);
    work(now<<1|1,tree[now].lazy);
    tree[now].lazy=0;
    return;
}
void build(int l,int r,int now)
{
    tree[now].l=l,tree[now].r=r;
    if(l==r) {tree[now].sum=val[rk[l]]%mod;return;}
    int m=l+r>>1;
    build(l,m,now<<1),build(m+1,r,now<<1|1);
    tree[now].sum=(tree[now<<1].sum+tree[now<<1|1].sum)%mod;
}
void modify(int l,int r,int now,int w)
{
    if(tree[now].l>=l&&tree[now].r<=r){work(now,w);return;}
    if(tree[now].lazy) pushdown(now);
    int m=tree[now].l+tree[now].r>>1;
    if(m>=l) modify(l,r,now<<1,w);
    if(m<r) modify(l,r,now<<1|1,w);
    tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;
}
int query(int now,int l,int r)
{
    if(tree[now].l>=l&&tree[now].r<=r) return tree[now].sum;
    if(tree[now].lazy) pushdown(now);
    int m=tree[now].l+tree[now].r>>1,res=0;
    if(l<=m) res=(res+query(now<<1,l,r))%mod;
    if(m<r) res=(res+query(now<<1|1,l,r))%mod;
    return res;
}
void update(int x,int y,int z)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        modify(id[top[x]],id[x],1,z);
        x=f[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    modify(id[x],id[y],1,z);
}
int query1(int x,int y)
{
    int res=0;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        res=(res+query(1,id[top[x]],id[x]))%mod;
        x=f[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    res=(res+query(1,id[x],id[y]))%mod;
    return res;
}
int main()
{
    read(n),read(m),read(root),read(mod);
    for(re int i=1;i<=n;i++) read(val[i]);
    for(re int i=1,x,y;i<n;i++) read(x),read(y),v[x].pb(y),v[y].pb(x);
    dfs1(root);dfs2(root,root);
    build(1,n,1);
    for(re int op,x,y,k,i=1;i<=m;i++)
    {
        read(op);
        if(op==1) read(x),read(y),read(k),update(x,y,k);
        else if(op==2) read(x),read(y),printf("%d
",query1(x,y));
        else if(op==3) read(x),read(y),modify(id[x],id[x]+siz[x]-1,1,y);
        else if(op==4) read(x),printf("%d
",query(1,id[x],id[x]+siz[x]-1));
    }
    return 0;
}

 

 

以上是关于树链剖分模板的主要内容,如果未能解决你的问题,请参考以下文章

模板时间◆模板·II◆ 树链剖分

树链剖分模板题(luogu3384 模板树链剖分)

树链剖分模板

BZOJ 2243--染色(树链剖分)

模板树链剖分

luoguP3384 模板树链剖分