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


    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;
            }
        }
    }
    
  • 相关阅读:
    Discuz论坛自动发帖机
    C#测试数据库连接是否成功
    JS重写提示框(confirm)
    随笔 选择
    随笔 诚实
    web项目经理手册【1】版本控制流程
    Asp.net多层架构中的变量引用与传递
    ASP.NET跨页面传值技巧总结
    web项目经理手册【3】Code Review
    web项目经理手册【7】项目经理需要铭记在心的话
  • 原文地址:https://www.cnblogs.com/mollnn/p/12887140.html
Copyright © 2020-2023  润新知