当前位置: 首页 > news >正文

权值树状数组

权值树状数组

权值数组研究的是数组的 值域 问题,经常应用于不重视数组的 元素顺序,更注重 元素内容 的场景。

单点修改,查询全局第 kkk

现在需要对一个数组进行两种操作

  1. pos x 表示将 a[pos]a[pos]a[pos] 的权值改成 xxx
  2. k 查询数组的全局第 kkk 小元素是谁。

如果 aaa 数组的 值域 以及每次 修改范围 不大,就可以用 cnt[i]cnt[i]cnt[i] 表示权值为 iii 的数的 出现次数

题目要求的是全局第 kkk 小元素,可以使用 二分 cntcntcnt 前缀和 的方式来完成。

所以需要动态维护 cntcntcnt 数组的前缀和,此时就可以用树状数组来维护。

初始时,创建一个 大小为值域 的数组 tree[i]tree[i]tree[i],维护以 [i−lowbit(i)+1,i][i-lowbit(i)+1,i][ilowbit(i)+1,i] 的区间信息。

然后进行 nnn单点修改aaa 的信息更新完,每次单点修改就是令 tree[a[pos]]tree[a[pos]]tree[a[pos]] 及其所有祖先加 111

对于操作 111,等价为 tree[a[pos]]tree[a[pos]]tree[a[pos]] 及其所有祖先减 111tree[x]tree[x]tree[x] 及其所有祖先加 111

对于操作 222,二分前缀和,但是每次求前缀和是 O(logn)O(logn)O(logn),故总时间是 O(log2n)O(log^2n)O(log2n)

二分前缀和是求出一个正整数 xxx 满足 xxx前缀和小于 kkkx+1x+1x+1前缀和大于等于 kkk

此时 x+1x+1x+1 就是全局第 kkk 小。

其实可以利用 树状数组的特性 来实现操作 222

已知 tree[i]tree[i]tree[i] 维护的是以 iii 结尾长度为 lowbit(i)lowbit(i)lowbit(i) 的区间信息,当 iii222 的幂的时候,维护的就是前缀和信息。

此时这个前缀和信息可以 O(1)O(1)O(1) 获得。

设初始状态 x=0x=0x=0sum=0sum=0sum=0,其中 xxx 表示第 kkk 小的数应该大于的数,sumsumsum 表示当前前缀和的值。

于是可以从最高的二进制位 log(n)log(n)log(n) 开始检查,对于当前二进制位 jjj 而言:

  1. sum+tree[x+2j]≥ksum+tree[x+2^j]\ge ksum+tree[x+2j]k,说明我们要找的数比 x+2jx+2^jx+2j 小。
  2. sum+tree[x+2j]<ksum+tree[x+2^j]<ksum+tree[x+2j]<k,说明我们要找的数比 x+2jx+2^jx+2j 大,所以 x:=2j,sum:=tree[x+2j]x:=2^j,sum:=tree[x+2^j]x:=2j,sum:=tree[x+2j]

最终找到的 x+1x+1x+1 就是全局第 kkk 小的元素。

#include <bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(2)
#define int long long
#define endl '\n'
#define PII pair<int,int>
#define INF 1e18template<typename T>// 单点修改和区间查询的树状数组
struct Fenwick {vector <T> tree;int n;Fenwick(int _n) : n(_n), tree(_n + 2){}// 求 1~x 的前缀和T getsum(int x) {T ans = 0;int L = x;while (x) {ans += tree[x];x = x - lowbit(x);}return ans;}// 区间查询T get_range_sum(int l, int r) {return getsum(r) - getsum(l - 1);}// 单点修改,是为了 range_add 服务void add(int x, T k) {while (x <= n) {tree[x] += k;x += lowbit(x);}}static inline int lowbit(int x) {return x & (-x);}T getKth(int k) {T x = 0, sum = 0;for (int i = log2(n); i >= 0; i--) {x += (1ll << i);if (x >= n || sum + tree[x] >= k) {x -= (1ll << i);} else {sum += tree[x];}               }return x + 1;}
};
void slove () {Fenwick<int> tree(n);
}signed main () {ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);slove();
}

http://www.dtcms.com/a/316694.html

相关文章:

  • 政务信息化项目建设管理办法的主要内容有哪些
  • 防火墙和网闸的区别,什么场景下,需要用到网闸?
  • iOS混淆工具有哪些?技术演进与选型趋势全景解析
  • 《C++》继承完全指南:从入门到精通
  • BeanFactory 和 ApplicationContext 的区别?
  • python-自定义抠图
  • 【分析学】内积空间中的线性算子
  • lumerical——多模干涉耦合器(MMI)
  • 机械学习--决策树(实战案例)
  • lumerical——Y分支功分器
  • Linux学习-数据结构(链表)
  • GISBox一键转换IFC到3DTiles
  • 【PCIE044】基于 JFM7VX690T 的全国产化 FPGA 开发套件
  • 分布式网关技术 + BGP EVPN,解锁真正的无缝漫游
  • 防火墙安全策略练习
  • PBX Feature Code(功能码)
  • 【DAB收音机】DAB系统架构介绍
  • mq_unlink系统调用及示例
  • 图像处理控件Aspose.Imaging教程:使用 C# 将 SVG 转换为 EMF
  • C++ 变量初始化方式总结 | 拷贝初始化 | 列表初始化 | 值初始化
  • 【PCB】3. 信号部分设计
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘keras’问题
  • Nginx入门:高性能Web服务器详解
  • 商用密码应用安全性评估(密评)实施指南:法律依据与核心要点解析
  • 神坛上的transformer
  • 如何测量滚珠花键的旋转方向间隙?
  • PYQT的QMessageBox使用示例
  • unity之 贴图很暗怎么办
  • Redis作为MySQL缓存的完整指南:从原理到实战
  • 《算法导论》第 4 章 - 分治策略