首页 > 其他分享 >【个人模板封装】树套树、高维数据结构

【个人模板封装】树套树、高维数据结构

时间:2023-07-30 21:24:04浏览次数:70  
标签:树套 树状 int vector resize 数组 BIT 数据结构 高维

前言

这是我个人使用的一些模板封装,限于个人能力,可能存在诸多不足与漏洞,在未加测试直接使用前请务必小心谨慎。更新可能会滞后于我本地的文档,如有疑问或者催更之类的可以在评论区留言。

全文模板测试均基于以下版本信息,请留意版本兼容问题。

Windows, 64bit
G++ (ISO C++20)
stack=268435456
开启O2优化

树状数组部分

树状数组

struct BIT {
    int n;
    vector<int> w;
    
    BIT() {}
    BIT(int n) {
        this->n = n; // 这里必须写 n ,否则会RE
        w.resize(n + 1);
    }
    void add(int x, int k) {
        for (; x <= n; x += x & -x) {
            w[x] += k;
        }
    }
    void add(int x, int y, int k) {
        add(x, k), add(y, -k);
    }
    int ask(int x) {
        int ans = 0;
        for (; x; x -= x & -x) {
            ans += w[x];
        }
        return ans;
    }
    int ask(int x, int y) {
        return ask(y) - ask(x - 1);
    }
    int kth(int k) { // 查找第k大的值
        int ans = 0;
        for (int i = __lg(n); i >= 0; i--) {
            int val = ans + (1 << i);
            if (val < n && w[val] < k) {
                k -= w[val];
                ans = val;
            }
        }
        return ans + 1;
    }
};

树状数组套树状数组(二维树状数组)1

请注意,该版本不能同时进行区间修改+区间查询。无离散化版本的空间占用为 \(\mathcal O(NM)\) 、建树复杂度为 \(\mathcal O(NM)\) 、单次查询复杂度为 \(\mathcal O(\log N\cdot \log M)\) 。

大致有以下两种写法,均通过模板题测试。

该部分模板题可参考:LOJ #133. 二维树状数组 1:单点修改,区间查询LOJ #134. 二维树状数组 2:区间修改,单点查询

借助一维树状数组进行拓展

struct BIT_2D {
    struct BIT {
        int n;
        vector<int> w;
        BIT() {}
        BIT(int n) {
            this->n = n; // 这里必须写 n ,否则会RE
            w.resize(n + 1);
        }
        void add(int x, int k) {
            for (; x <= n; x += x & -x) {
                w[x] += k;
            }
        }
        int ask(int x) {
            int ans = 0;
            for (; x; x -= x & -x) {
                ans += w[x];
            }
            return ans;
        }
    };
    int n;
    vector<BIT> w;
    
    BIT_2D() {}
    BIT_2D(int n, int m) {
        this->n = n;
        w.resize(n + 1);
        for (int i = 1; i <= n; i++) {
            w[i] = BIT(m);
        }
    }
    void add(int x, int y, int k) {
        for (; x <= n; x += x & -x) {
            w[x].add(y, k);
        }
    }
    void add(int x, int y, int X, int Y, int k) { // 区块修改:二维差分
        X++, Y++;
        add(x, y, k), add(X, y, -k);
        add(X, Y, k), add(x, Y, -k);
    }
    int ask(int x, int y) { // 单点查询
        int ans = 0;
        for (; x; x -= x & -x) {
            ans += w[x].ask(y);
        }
        return ans;
    }
    int ask(int x, int y, int X, int Y) { // 区块查询:二维前缀和
        x--, y--;
        return ask(X, Y) - ask(x, Y) - ask(X, y) + ask(x, y);
    }
};

压缩优化

struct BIT_2D {
    int n, m;
    vector<vector<int>> w;
    
    BIT_2D(int n, int m) : n(n), m(m) {
        w.resize(n + 1, vector<int>(m + 1));
    }
    void add(int x, int y, int k) {
        for (int i = x; i <= n; i += i & -i) {
            for (int j = y; j <= m; j += j & -j) {
                w[i][j] += k;
            }
        }
    }
    void add(int x, int y, int X, int Y, int k) { // 区块修改:二维差分
        X++, Y++;
        add(x, y, k), add(X, y, -k);
        add(X, Y, k), add(x, Y, -k);
    }
    int ask(int x, int y) { // 单点查询
        int ans = 0;
        for (int i = x; i; i -= i & -i) {
            for (int j = y; j; j -= j & -j) {
                ans += w[i][j];
            }
        }
        return ans;
    }
    int ask(int x, int y, int X, int Y) { // 区块查询:二维前缀和
        x--, y--;
        return ask(X, Y) - ask(x, Y) - ask(X, y) + ask(x, y);
    }
};

树状数组套树状数组(二维树状数组)2

该版本支持全部操作。但是全部复杂度均比上一个版本多 \(4\) 倍。

这里仅提供压缩优化版。

该部分模板题可参考:LOJ #135. 二维树状数组 3:区间修改,区间查询

struct BIT_2D {
    int n, m;
    vector<vector<int>> b1, b2, b3, b4;
    
    BIT_2D(int n, int m) : n(n), m(m) {
        b1.resize(n + 1, vector<int>(m + 1));
        b2.resize(n + 1, vector<int>(m + 1));
        b3.resize(n + 1, vector<int>(m + 1));
        b4.resize(n + 1, vector<int>(m + 1));
    }
    void add(auto &w, int x, int y, int k) { // 单点修改
        for (int i = x; i <= n; i += i & -i) {
            for (int j = y; j <= m; j += j & -j) {
                w[i][j] += k;
            }
        }
    }
    void add(int x, int y, int k) { // 多了一步计算
        add(b1, x, y, k);
        add(b2, x, y, k * (x - 1));
        add(b3, x, y, k * (y - 1));
        add(b4, x, y, k * (x - 1) * (y - 1));
    }
    void add(int x, int y, int X, int Y, int k) { // 区块修改:二维差分
        X++, Y++;
        add(x, y, k), add(X, y, -k);
        add(X, Y, k), add(x, Y, -k);
    }
    int ask(auto &w, int x, int y) { // 单点查询
        int ans = 0;
        for (int i = x; i; i -= i & -i) {
            for (int j = y; j; j -= j & -j) {
                ans += w[i][j];
            }
        }
        return ans;
    }
    int ask(int x, int y) { // 多了一步计算
        int ans = 0;
        ans += x * y * ask(b1, x, y);
        ans -= y * ask(b2, x, y);
        ans -= x * ask(b3, x, y);
        ans += ask(b4, x, y);
        return ans;
    }
    int ask(int x, int y, int X, int Y) { // 区块查询:二维前缀和
        x--, y--;
        return ask(X, Y) - ask(x, Y) - ask(X, y) + ask(x, y);
    }
};

标签:树套,树状,int,vector,resize,数组,BIT,数据结构,高维
From: https://www.cnblogs.com/WIDA/p/17592060.html

相关文章

  • 考研数据结构——每日一题[表达式求值]
    3302.表达式求值给定一个表达式,其中运算符仅包含+,-,*,/(加减乘整除),可能包含括号,请你求出表达式的最终值。注意:数据保证给定的表达式合法。题目保证符号-只作为减号出现,不会作为负号出现,例如,-1+2,(2+2)*(-(1+1)+2)之类表达式均不会出现。题目保证表达式中所有数字均为......
  • 数据结构基础
    逻辑结构和物理结构记录一下最近开始学习的数据结构与算法逻辑结构是指数据对象中数据元素之间的相互关系。集合结构集合结构中数据元素,除了都属于一个集合外,无其它关系线性结构数据元素之间是一对一的关系树形结构数据元素之间存在一对多的关系圆形结构数据元素存在多对多的关系物......
  • 37 pinctrl(三)数据结构
    1.pinctrl在devicetree中的定义和使用2.pinctrldriverinit3.常用数据结构pinctrl驱动的注册主要实现函数structpinctrl_dev*pinctrl_register(structpinctrl_desc*pctldesc, structdevice*dev,void*driver_data)从设备树中获取pinctrl_desc,然后将......
  • 408-数据结构算法题笔记
    常用基本操作1.定义整数无穷大#defineINT_MAX=0x7f7f7f7f;2.绝对值函数intabs_(intx){ if(x<0)return-x; returnx;}3.最大最小值函数(一般可以直接写吧)intmin(inta,intb){ if(a<b)returna; returnb;}说明时空间复杂度可以先设neg:代码规范1.函......
  • 考研数据结构——每日一题 [日期]
    3573.日期累加设计一个程序能计算一个日期加上若干天后是什么日期。输入格式第一行包含整数T,表示共有T组测试数据。每组数据占一行,包含四个整数y,m,d,a,分别表示给定日期的年、月、日和累加的天数。输出格式每组数据输出一行,一个结果,每行按yyyy-mm-dd的格式输出。数据......
  • 【数据结构】B树和B+树
    这部分内容较少,B树要理解基本特性,掌握其建立、插入和删除操作;B+树只需要掌握基本概念即可1.B树及其基本操作b树是在平衡二叉树的基础上的衍生概念(1)B树的定义:m阶B树即为所有结点的平衡因子均等于0的m路平衡查找树复习:m叉树指的是结点的最大子树数目,而不是说m叉树的每个非叶结点......
  • 5 线性数据结构 参考代码
    P3156[深基15.例1]询问学号#include<cstdio>constintMAXN=2000005;inta[MAXN];intmain(){intn,m;scanf("%d%d",&n,&m);for(inti=0;i<n;++i)scanf("%d",&a[i]);while(m--){int......
  • 数据结构之带头节点的单链表增删改查操作实现
     单链表的定义什么是单链表   单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。   单链表的各个数据元素在物理上可以是离散存放的,每个结点除了存放数据元素外,还要存储指向下一个节点的指针。而顺序表是连续存放的,每个结点中只......
  • 数据结构中队列的存储和应用
    队列:只有两个口进出数据,一个专门进入数据,另一个专门出数据,先进先出,FIFO表 一、顺序队列:存储元素的连续内存的首地址容量队头位置(出队)队尾位置(入队)[元素数量]运算:创建、销毁、清空、出队、入队、队空、队满、队头、队尾、元素数量#inclu......
  • 算法学习(一)—— 如何看待数据结构与算法
    绪言最近在通过阅读K神的《Hello算法》学习数据结构与算法的知识,同时做一些博客笔记记录,方便日后的查找和复习算法数据结构与算法统称算法认识算法算法更多的是一种逻辑,例如:查阅字典的原理与二分查找算法相一致。二分查找体现了分而治之的重要算法思想。整理扑克的过......