• 树链剖分


    先粘模板, 然后再粘一个入门题的代码.

    #include <cstdio>
    #include <algorithm>
    
    #define lson rt<<1
    #define rson rt<<1|1
    
    using namespace std;
    
    typedef long long ll;
    
    const ll maxn = 1e5+500;
    
    int qsz, qcnt;
    ll date[maxn];
    int head[maxn];
    int deep[maxn];
    int size[maxn];
    int  top[maxn];  // 重链的起点. 
    int  son[maxn];
    int   id[maxn];  //  节点u的dfs序号 
    int   rk[maxn];  //  dfs序号为i的节点  如果使用线段树之类的, build里应该使用 rk 
    int   pa[maxn];  //  父节点 
    
    //  First dfs is aim to getting son[], size[] and deep[] pa[]
    int dfs(int u, int fa) {
        int i, v, sz = 1, t1; 
        deep[u] = deep[fa] + 1;
        son[u] = u; size[u] = 0;
        pa[u] = fa;
        for (i=head[u]; i; i=edge[i].lst) {
            v = edge[i].to;
            if (v == fa) continue;
            t1 = dfs(v, u);
            sz += t1;
            if (size[son[u]] < t1) son[u] = v;
        }
        size[u] = sz;
        return sz;
    }
    
    // Second dfs is aim to getting id[] rk[] top[]
    void dfs2(int u, int fa, int t) {
        int i, v;
        top[u] = t; id[u] = qcnt; rk[qcnt++] = u; // update top[] id[] rk[]  
        if (son[u] != u) dfs2(son[u], u, t);
        for (i=head[u]; i; i=edge[i].lst) {
            v = edge[i].to;
            if (v == fa || son[u] == v) continue;
            dfs2(v, u, v);  // 轻儿子 top is itself.
        }
    }
    
    ll op(int x, int y) {
        int fx = top[x], fy = top[y];
        ll res = 0;
        while (fx != fy) {
             // 比较top的深度  来选择那个节点需要移动
             // 选择深度比较深的节点向上移动.
             // 这儿定义 fy的深度比较深 
            if (deep[fx] > deep[fy]) {  
                swap(fx, fy);
                swap(x, y);    
            }
            res = (res + query(id[fy], id[y], 1)); // query()是你维护方式, 这儿用的线段树维护. 
            y = pa[fy];     // 这条top链已经获取好信息了, 所以应该是 pa[fy] 
            fy = top[y];    // 继续走 
        } 
        // 最后 fx fy在同一条链上.  dfs序深度浅的小, 深度深的大. 
        if (id[x] <= id[y]) res += query(id[x], id[y], 1);
        else res += query(id[y], id[x], 1);
        return res;
    }
    
    // 树链剖分要修改某一棵子树, 就是修改这段区间[id[x], id[x]+size[x]-1]   注,size[x]包含x节点. 
    
    int main()
    {
    
        // init 
        qsz = 1; qcnt = 1;
        deep[0] = 0;
        dfs(1, 0); dfs2(1, 0, 1);
     
        
        return 0;
    }

    入门题  HYSBZ - 4034 

    #include <cstdio>
    #include <algorithm>
    
    #define lson rt<<1
    #define rson rt<<1|1
    
    using namespace std;
    
    typedef long long ll;
    
    const ll maxn = 1e5+500;
    
    int qsz, qcnt;
    ll date[maxn];
    int head[maxn];
    int deep[maxn];
    int size[maxn];
    int  top[maxn];
    int  son[maxn];
    int   id[maxn];  //  ½ÚµãuµÄdfsÐò 
    int   rk[maxn];  //  dfsΪiµÄ½Úµã 
    int   pa[maxn];  //  ½ÚµãuµÄ¸¸½Úµã 
    
    struct nobe {
        int to;
        int lst;
    }edge[maxn<<1];
    
    inline void add(int u, int v) {
        edge[qsz].to = v;
        edge[qsz].lst = head[u];
        head[u] = qsz++;
    }
    
    //  First dfs is aim to getting son[], size[] and deep[] pa[]
    int dfs(int u, int fa) {
        int i, v, sz = 1, t1; 
        deep[u] = deep[fa] + 1;
        son[u] = u; size[u] = 0;
        pa[u] = fa;
        for (i=head[u]; i; i=edge[i].lst) {
            v = edge[i].to;
            if (v == fa) continue;
            t1 = dfs(v, u);
            sz += t1;
            if (size[son[u]] < t1) son[u] = v;
        }
        size[u] = sz;
        return sz;
    }
    
    // Second dfs is aim to getting id[] rk[] top[]
    void dfs2(int u, int fa, int t) {
        int i, v;
        top[u] = t; id[u] = qcnt; rk[qcnt++] = u; // update top[] id[] rk[]  
        if (son[u] != u) dfs2(son[u], u, t);
        for (i=head[u]; i; i=edge[i].lst) {
            v = edge[i].to;
            if (v == fa || son[u] == v) continue;
            dfs2(v, u, v);  // ~~~link top is itself.
        }
    }
    
    
    struct nobe2 {
        int l;
        int r;
        ll val;
        ll lazy;
        void fun(ll jval) {
             val += jval * (r - l + 1);
            lazy += jval;
        }
    }te[maxn<<2];
    
    inline void pshup(int rt) {
        te[rt].val = te[lson].val + te[rson].val;
    }
    
    void build(int l, int r, int rt) {
        te[rt].l = l; te[rt].r = r;
        te[rt].lazy = 0;
        if (l == r) {
            te[rt].val = date[rk[l]]; // rk[l]
            return ;
        }
        int m = (l + r) >> 1;
        build(l, m, lson);
        build(m+1, r, rson);
        pshup(rt);
    }
    
    inline void pshdwn(int rt) {
        if (te[rt].lazy) {
            te[lson].fun(te[rt].lazy);
            te[rson].fun(te[rt].lazy);
            te[rt].lazy = 0;
        }
    }
    
    void update(int l, int r, ll val, int rt) {
        if (l>te[rt].r || r<te[rt].l) return ;
        if (l<=te[rt].l && r>=te[rt].r) {
            te[rt].fun(val);
            return ;
        }
        pshdwn(rt);
        update(l, r, val, lson);
        update(l, r, val, rson);
        pshup(rt);
    }
    
    ll query(int l, int r, int rt) {
        if (l>te[rt].r || r<te[rt].l) return 0;
        if (l<=te[rt].l && r>=te[rt].r) return te[rt].val;
        pshdwn(rt);
        return  (query(l, r, lson) + query(l, r, rson));
    }
    
    ll op2(int x, int y) {
        int fx = top[x], fy = top[y];
        ll res = 0;
        while (fx != fy) {
            if (deep[fx] > deep[fy]) {
                swap(fx, fy);
                swap(x, y);    
            }
            res = (res + query(id[fy], id[y], 1));
            y = pa[fy];
            fy = top[y];
        } 
        if (id[x] <= id[y]) res += query(id[x], id[y], 1);
        else res += query(id[y], id[x], 1);
        return res;
    }
    
    void op3(int x, ll z) {
        update(id[x], id[x] + size[x] - 1, z, 1);
    }
    
    int main()
    {
        int n, m;
        int i, j, u, v, op, x, y;
        ll z;
        // init 
        qsz = 1; qcnt = 1;
        
        scanf("%d%d", &n, &m);
        for (i=1; i<=n; ++i) scanf("%lld", date+i);
        for (i=1; i<n; ++i) {
            scanf("%d%d", &u, &v);
            add(u, v);
            add(v, u);
        }
        
        deep[0] = 0;
        dfs(1, 0); dfs2(1, 0, 1);
        build(1, n, 1);
     
        while (m--) {
            scanf("%d", &op);
            switch (op) {
            case 1:
                scanf("%d%lld", &x, &z);
                update(id[x], id[x], z, 1);
                break;
            case 2:
                scanf("%d%lld", &x, &z);
                op3(x, z);
                break;
            case 3:
                scanf("%d", &x);
                printf("%lld
    ", op2(1, x));
                break;                            
            }
        }
        
        return 0;
    }
  • 相关阅读:
    关于投资的思考(95) 熊市的几个感性指标,Luna暴雷的次级灾害,美联储加息75个基点,俄乌冲突升级能源价格大涨
    关于投资的思考(94) 以太跌到1000附近,大饼跌到2万附近,熊市的几个感性指标和段子
    关于投资的思考(93) 以太大跌的原因和抄底策略讨论,马丁策略,关于NFT国内数藏,抢鲸探的经验
    关于投资的思考(96) 比特币跌破18000关机价,以太跌破882,是否可以抄底了?塔勒布三部曲,熊市的几个参考指标
    string to base64 or base64 to string in ms sql server
    convert datetime to timestamp in ms sql server
    React Suspense 尝鲜,处理前后端IO异步操作
    基于Vite+React构建在线Excel
    CentOS中实现基于Docker部署BI数据分析
    BI与SaaS碰撞,让数据处理更加轻松(下)
  • 原文地址:https://www.cnblogs.com/cgjh/p/9491399.html
Copyright © 2020-2023  润新知