ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[P3384] 【模板】轻重链剖分 - 树链剖分

2020-05-14 11:04:43  阅读:227  来源: 互联网

标签:链剖分 剖分 int top t2 树链 dep did void


Description

已知一棵包含 \(N\) 个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作:

操作 \(1\): 格式: \(1\ x\ y\ z\) 表示将树从 \(x\) 到 \(y\) 结点最短路径上所有节点的值都加上 \(z\)。

操作 \(2\): 格式: \(2\ x\ y\) 表示求树从 \(x\) 到 \(y\) 结点最短路径上所有节点的值之和。

操作 \(3\): 格式: \(3\ x\ z\) 表示将以 \(x\) 为根节点的子树内所有节点值都加上 \(z\)。

操作 \(4\): 格式: \(4\ x\) 表示求以 \(x\) 为根节点的子树内所有节点值之和

Solution

复习一下模板

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 400005;

int val[N],tag[N];

void pushup(int p) {
    val[p]=val[p*2]+val[p*2+1];
}
void pushdown(int p,int l,int r) {
    if(tag[p]) {
        val[p*2]+=tag[p]*((l+r)/2-l+1);
        val[p*2+1]+=tag[p]*(r-(l+r)/2);
        tag[p*2]+=tag[p];
        tag[p*2+1]+=tag[p];
        tag[p]=0;
    }
}
void build(int p,int l,int r,int *src) {
    if(l==r) val[p]=src[l];
    else {
        build(p*2,l,(l+r)/2,src);
        build(p*2+1,(l+r)/2+1,r,src);
        pushup(p);
    }
}
void modify(int p,int l,int r,int ql,int qr,int key) {
    if(l>qr || r<ql) return;
    if(l>=ql && r<=qr) {
        val[p]+=(r-l+1)*key;
        tag[p]+=key;
    }
    else {
        pushdown(p,l,r);
        modify(p*2,l,(l+r)/2,ql,qr,key);
        modify(p*2+1,(l+r)/2+1,r,ql,qr,key);
        pushup(p);
    }
}
int query(int p,int l,int r,int ql,int qr) {
    if(l>qr || r<ql) return 0;
    if(l>=ql && r<=qr) {
        return val[p];
    }
    else {
        pushdown(p,l,r);
        return query(p*2,l,(l+r)/2,ql,qr)+query(p*2+1,(l+r)/2+1,r,ql,qr);
    }
}

vector <int> g[N];

int top[N],wson[N],siz[N],dep[N],vis[N],tid[N],did[N],fin[N],fa[N],cnt=0;

void link(int p,int q) {
    g[p].push_back(q);
    g[q].push_back(p);
}

void dfs1(int p) {
    vis[p]=siz[p]=1;
    for(int q:g[p]) if(vis[q]==0) {
        dep[q]=dep[p]+1;
        fa[q]=p;
        dfs1(q);
        siz[p]+=siz[q];
        if(siz[q]>siz[wson[p]]) wson[p]=q;
    }
}

void dfs2(int p) {
    did[p]=++cnt;
    tid[cnt]=p;
    vis[p]=1;
    if(wson[p]) top[wson[p]]=top[p],dfs2(wson[p]);
    for(int q:g[p]) if(vis[q]==0) {
        top[q]=q;
        dfs2(q);
    }
    fin[p]=cnt;
}

int n,m,r,mod,v[N],w[N];

void presolve() {
    dep[r]=1;
    dfs1(r);
    memset(vis,0,sizeof vis);
    top[r]=r;
    dfs2(r);
}



void link_modify(int p,int q,int v) {
    while(top[p]-top[q]) {
        if(dep[top[p]]>dep[top[q]]) swap(p,q);
        modify(1,1,n,did[top[q]],did[q],v);
        q=fa[top[q]];
    }
    if(dep[p]>dep[q]) swap(p,q);
    modify(1,1,n,did[p],did[q],v);
}

int link_query(int p,int q) {
    int ans=0;
    while(top[p]-top[q]) {
        if(dep[top[p]]>dep[top[q]]) swap(p,q);
        ans+=query(1,1,n,did[top[q]],did[q]);
        q=fa[top[q]];
    }
    if(dep[p]>dep[q]) swap(p,q);
    ans+=query(1,1,n,did[p],did[q]);
    return ans;
}

signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>m>>r>>mod;
    for(int i=1;i<=n;i++) cin>>v[i];
    for(int i=1;i<n;i++) {
        int t1,t2;
        cin>>t1>>t2;
        link(t1,t2);
    }
    presolve();
    for(int i=1;i<=n;i++) w[did[i]]=v[i];
    build(1,1,n,w);
    for(int i=1;i<=m;i++) {
        int t1,t2,t3,t4;
        cin>>t1;
        if(t1==1) {
            cin>>t2>>t3>>t4;
            link_modify(t2,t3,t4);
        }
        if(t1==2) {
            cin>>t2>>t3;
            cout<<link_query(t2,t3)%mod<<endl;
        }
        if(t1==3) {
            cin>>t2>>t3;
            modify(1,1,n,did[t2],fin[t2],t3);
        }
        if(t1==4) {
            cin>>t2;
            cout<<query(1,1,n,did[t2],fin[t2])%mod<<endl;
        }
    }
}

标签:链剖分,剖分,int,top,t2,树链,dep,did,void
来源: https://www.cnblogs.com/mollnn/p/12887140.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有