zoukankan      html  css  js  c++  java
  • 【数据结构】树状数组

    单点加值,区间求和

    这个是最基础的树状数组的用法了。初始值是Init之后一个一个Add上去的。

    struct BinaryIndexTree {
    
        static const int MAXN = 500000 + 5;
    
        int n;
        int sm[MAXN];
    
        void Add(int x, int v) {
            for(int i = x; i <= n; i += i & (-i))
                sm[i] += v;
        }
    
        ll Sum(int x) {
            ll res = 0;
            for(int i = x; i; i -= i & (-i))
                res += sm[i];
            return res;
        }
    
        void Init(int _n) {
            n = _n;
            memset(sm, 0, sizeof(sm[0]) * (n + 1));
        }
    
    } bit;
    

    已通过:
    https://www.luogu.com.cn/problem/P3374

    单点改值,区间求和

    额外记录一个va数组,然后每次比对这次要“加”的值是多少,套用单点加值。

    struct BinaryIndexTree {
    
        static const int MAXN = 500000 + 5;
    
        int n;
        int va[MAXN];
        int sm[MAXN];
    
        void Add(int x, int v) {
            for(int i = x; i <= n; i += i & (-i))
                sm[i] += v;
        }
    
        ll Sum(int x) {
            ll res = 0;
            for(int i = x; i; i -= i & (-i))
                res += sm[i];
            return res;
        }
    
        void Init(int _n) {
            n = _n;
            memset(va, 0, sizeof(va[0]) * (n + 1));
            memset(sm, 0, sizeof(sm[0]) * (n + 1));
        }
    
        void Modify(int x, int v) {
            int d = v - va[x];
            Add(x, d);
            va[x] = v;
        }
    
    } bit;
    

    二维偏序

    namespace BinaryIndexTree {
    
        const int MAXN = 200000 + 5;
    
        int n;
        int nn;
        int a[MAXN];
        int aa[MAXN];
    
        int bit[MAXN];
    
        void Add(int x, int v) {
            for(int i = x; i <= nn; i += i & (-i))
                bit[i] += v;
        }
    
        ll Sum(int x) {
            ll res = 0;
            for(int i = x; i; i -= i & (-i))
                res += bit[i];
            return res;
        }
    
        void Init1() {
            n = 0;
            nn = 0;
        }
    
        void Insert(int v) {
            a[++n] = v;
            aa[++nn] = v;
        }
    
        void Init2() {
            sort(aa + 1, aa + 1 + nn);
            nn = unique(aa + 1, aa + 1 + nn) - (aa + 1);
            memset(bit, 0, sizeof(bit[0]) * (nn + 1));
            for(int i = 1; i <= n; ++i) {
                a[i] = lower_bound(aa + 1, aa + 1 + nn, a[i]) - aa;
                Add(a[i], 1);
            }
        }
    
    }
    

    区间修改区间求和

    设差分数组 (d_i=a_i-a_{i-1}) ,显然有 (a_i=sumlimits_{j=1}^i d_j) ,那么 (Sum(x)=sumlimits_{i=1}^x a_i=sumlimits_{i=1}^x sumlimits_{j=1}^i d_j = sumlimits_{i=1}^x (x-i+1)*d_i=(x+1)sumlimits_{i=1}^xd_i - sumlimits_{i=1}^x i*d_i)

    struct BinaryIndexTree {
    //    const int MAXN = 3e5 + 5;
        int n;
        ll d1[MAXN], d2[MAXN];
        void Add(int x, int v) {
            for(int i = x; i <= n; i += i & (-i)) d1[i] += v, d2[i] += 1LL * x * v;
        }
        ll Sum(int x) {
            ll res = 0;
            for(int i = x; i; i -= i & (-i)) res += 1LL * (x + 1) * d1[i] - d2[i];
            return res;
        }
        int RangeAdd(int l, int r, int v) {
            Add(l, v), Add(r + 1, -v);
        }
        ll RangeSum(int l, int r) {
            return Sum(r) - Sum(l - 1);
        }
        void Init(int _n) {
            n = _n;
            memset(d1, 0, sizeof(d1[0]) * (n + 1));
            memset(d2, 0, sizeof(d2[0]) * (n + 1));
        }
    } bit;
    
  • 相关阅读:
    手工卸载.Net写的win服务
    程序员素质面试题
    GridView数据导出功能
    使用EventLog类写系统日志
    HTML Response ContentType 大全
    用C#做短信CMPP2.0/3.0协议 支持扩展号支持物理网卡
    CYQ.Data 轻量数据层之路 使用篇MAction 数据查询 视频 E (二十二)
    CYQ.Data 轻量数据层之路 V2.0 震撼惊世 支持多数据库/内置Aop(二十五)
    MapXtreme 2005 GIS开发入门系列 索引
    CYQ.Data 轻量数据层之路 框架如何应对数据库变化
  • 原文地址:https://www.cnblogs.com/purinliang/p/13672344.html
Copyright © 2011-2022 走看看