DS
树状数组
原始问题
- \(a_x \overset+\gets y\)
- \(\sum\limits_{i=1}^{r} a_i\)
解决方法:
定义 \({\rm lb}(i) = i-i \wedge (i-1)\)
定义 \(f(i) = i \wedge (i-1)\),\(f(0)=0\)。
可以发现 \(f^{\left\lfloor(\log_2 n+1)\right\rfloor}(n)=0\)。
另外地,\(\log_2 {\rm lb}(x)\) 正好是 \(x\) 的二进制表示 \(\sum\limits^{\infty}_{i=0}k_i2^i\) 的从右往左的第一个零的位置(最低位是 \(0\) 位),或者说 \({\rm lb}(x) = 2^{\min\{i \in \mathbf N \mid k_i=1\}}\)。
因此 \({\rm lb}(2^\lambda) = 2^\lambda(\lambda \in \mathbf N)\)。
考虑利用 \({\rm lb}\) 和 \(f\) 函数进行操作,将 \(1 \sim r\) 划分为 \(\le \log_2 n+1\) 的区间。
考虑化为 \((f(n),n]\),可以通过一个数组 \(b\) 解决。
令 \(q\) 为前缀和数组,显然有 \(q_n = q_{f(n)} + b_n\)。
我们考虑修改操作,相当于解一个方程组 \(f(x) \le n\),因为 \(f(x) = x - {\rm lb}(x)\),所以 \(x - {\rm lb}(x) \le n \Longrightarrow {\rm lb}(x) \ge x-n\),考虑枚举 \({\rm lb}(x) = r\),可以发现满足条件的 \(x\) 最多只有一个:\(x = \left\lceil \dfrac n r\right\rceil r\),但是有时求解出的 \({\rm lb}(x) \ne r\),这时候说明 \({\rm lb}(n) > r\),此时没有满足条件的解。
由于 \(f^{\left\lfloor(\log_2 n+1)\right\rfloor}(n)=0\),所以统计一次前缀和的复杂度为 \(O(\log L)\)(L 为数组长度,下同),又因为对于每个 \({\rm lb}(x)\) 最多只有一个 \(x\),而且 \({\rm lb}(x) = 2^\lambda(\lambda \in \mathbf N)\),所以最多只有 \(\left\lfloor\log_2 L+1\right\rfloor\) 个解,所以单点修改的复杂度为 \(O(\log n)\),完毕。
给出伪代码:
Variables:
T: Array[Int] // 树状数组变量
L: Int // 大小
Functions:
f(x: Int) -> Int = x & (x-1)
lb(x: Int) -> Int = x - f(x)
Query(ind: Int) -> Int = ans: // 查询前缀和
ans = 0
while ind != 0
ans = ans + T[ind]
ind = f(ind)
Modify(ind: Int, val: Int) -> Null:
t: Int = 1
while t <= L
x: Int = ceil(ind/t)*t
if lb(x) == t
T[x] = T[x] + val
t = 2t
树状数组的 modify
有一种等价写法:
Modify(ind: Int, val: Int) -> Null:
while ind <= L
T[ind] = T[ind] + val
ind = ind + lb(ind)
这个方法我暂时没有找到严格的数学证明,这里给一张图。
(贺的)
前缀修改,单点查询
- \(\forall i \in [1, R],a_i \overset+\gets y\)
- \(a_x\)
通过差分,可以轻松解决。
multiset
个数查询
- 删除一个 \([1, R]\)
- 加入一个 \([1, R]\)
- 求 \(x\) 在集合中出现了多少次
建立一个桶数组,删除就是 \(\forall i \in [1, R],a_i \overset-\gets 1\),加入就是 \(\forall i \in [1, R],a_i \overset+\gets 1\),于是转化为前缀修改,单点查询。有时需要离散化。这种方法叫做 权值树状数组。
动态 multiset
第 \(K\) 小
- 加入一个 \(x\)
- 删除一个 \(x\)
- 求集合第 \(K\) 小
考虑权值树状数组,12 操作显然,3 操作可以直接二分,查询从 \(0 \sim x\) 的个数,转化为单点修改,前缀查询,注意,\(3\) 操作的时间复杂度为 \(O(\log^2 L)\)
二维偏序
考虑逆序对问题:建立权值树状数组,每次先插入 \(a_i\),然后查询 \((a_i,\max a]\) 的个数(因为此时进这个集合的一定下标 \(\le i\),而且 \(a_i \not> a_i\),所以是 \(i<j \wedge a_i>a_j\) 的个数),通过建立第一维的顺序可以求二维偏序。
前缀修改,前缀查询
- \(\forall i \in [1, R],a_i \overset+\gets y\)
- \(\sum\limits_{i=1}^{r} a_i\)
考虑差分。题目变为
- \(a_i \overset+\gets y\)
- \(\sum\limits^{R}_{i=1}\sum\limits^{i}_{j=1} a_j=\sum\limits^{R}_{i=1} (R-i+1)a_i=\sum\limits^{R}_{i=1} Ra_i-ia_i+a_i=(R+1)\sum\limits^{R}_{i=1}a_i-\sum\limits^{R}_{i=1}ia_i\)
考虑维护两个树状数组,分别维护 \(a_i\) 和 \(ia_i\),即可解决。
PM+PPQ
- \(\forall i \in [1, R],a_i \overset+\gets y\)
- \(\sum\limits_{i=1}^{r} \sum\limits_{j=1}^{i} a_j\)
考虑差分。题目变为
- \(a_i \overset+\gets y\)
- \(\sum\limits^{R}_{i=1}\sum\limits^{i}_{j=1}\sum\limits^{j}_{k=1} a_k=\sum\limits^{R}_{i=1}(i\sum\limits^{i}_{j=1}a_j)+\sum\limits^{R}_{i=1}(\sum\limits^{i}_{j=1}a_j)-\sum\limits^{R}_{i=1}\sum\limits^{i}_{j=1}ja_j-\text{Lazy,懒得退了,反正里面是一个多项式}\)
DS的更多相关文章
- 创建Azure DS 虚拟机并附加SSD硬盘
$subscriptionName = "Windows Azure Enterprise Trial" #订阅名称 $location = "China East&qu ...
- DS实验题 融合软泥怪-2 Heap实现
题目和STL实现:DS实验题 融合软泥怪-1 用堆实现优先队列 引言和堆的介绍摘自:Priority Queue(Heaps)--优先队列(堆) 引言: 优先队列是一个至少能够提供插入(Insert) ...
- Hyper-V 2012 R2 故障转移群集之建立域控(AD DS)与加入域
Windows 2012 R2建立域控(AD DS)与加入域 Active Directory概述: 使用 Active Directory(R) 域服务 (AD DS) 服务器角 ...
- dataGridViewX和数据库的链接之dataGridViewX1.DataSource = ds.Tables[0];
dataGridViewX1.DataSource = ds.Tables[0]; 1, dataGridViewX和数据库链接,如果我们用 dataGridViewX1.DataSource = d ...
- Windows Azure Virtual Machine (26) 使用高级存储(SSD)和DS系列VM
<Windows Azure Platform 系列文章目录> Update: 2016-11-3,如果大家在使用Linux VM,使用FIO进行IOPS测试的时候,请使用以下命令: su ...
- DS Tree 已知后序、中序 => 建树 => 求先序
注意点: 和上一篇的DS Tree 已知先序.中序 => 建树 => 求后序差不多,注意的地方是在aftorder中找根节点的时候,是从右往左找,因此递归的时候注意参数,最好是拿纸和笔模拟 ...
- [DS Basics] Data structures
1, LinkedList composed of one and one Node: [data][next]. [head] -> [data][next] -> [data][nex ...
- DS实验题 Old_Driver UnionFindSet结构 指针实现邻接表存储
题目见前文:DS实验题 Old_Driver UnionFindSet结构 这里使用邻接表存储敌人之间的关系,邻接表用指针实现: // // main.cpp // Old_Driver3 // // ...
- DS实验题 Dijkstra算法
参考:Dijkstra算法 数据结构来到了图论这一章节,网络中的路由算法基本都和图论相关.于是在拿到DS的实验题的时候,决定看下久负盛名的Dijkstra算法. Dijkstra的经典应用是开放最短路 ...
- XLAT转码:以DS:【BX+AL】为地址,提取存储器中的一个字节再送入AL
data segment a db ,,,,,,,, b dw ;sum of a table db 11h,22h,33h,44h,55h,66h,77h,88h,99h ends code seg ...
随机推荐
- Redis实现延迟队列的正确姿势
在之前探讨延时队列的文章中我们提到了 redisson delayqueue 使用 redis 的有序集合结构实现延时队列,遗憾的是 go 语言社区中并无类似的库.不过问题不大,没有轮子我们自己造. ...
- JavaScript中DOM查询封装函数
在JavaScript中可以通过BOM查询html文档中的元素,也就是所谓的在html中获取对象然后对它添加一个函数. 常用的方法有以下几种: ①document.getElementById() 通 ...
- JavaScript做简单的购物车效果(增、删、改、查、克隆)
比如有时候遇到下面这种情况,点击加入购物车,然后在上方的购物车中动态的添加商品以及商品的信息,我们就可以通过JavaScript实现简单的这些操作. 首先我们需要在html文档中,通过css对页面的布 ...
- wcf .net webService和 .net webApi的联系与差异
首先,我们需要清楚它们的概念,然后才能走好下一步. wcf是对于ASMX,.Net Remoting,Enterprise Service,WSE,MSMQ等技术的整合,它是一种重量级消息交互框架,广 ...
- 520到了,作为一个python程序员,必须整点肤白貌美的爬虫代码给你们~
马上520就快到啦~ 整点好看的给你们看下~ 直接开搞~ 代码流程 模拟浏览器向服务器发送一个http请求,网站接收到请求后返回数据.在写爬虫代码的时候一定先要去模拟浏览器访问,因为现在的网站当接收到 ...
- idea 在创建maven时没有src的解决方法
在创建maven时 加上archetypeCatalog=internal
- 用面向对象的方式操作 JSON 甚至还能做四则运算 JSON 库
前言 在之前实现的 JSON 解析器中当时只实现了将一个 JSON 字符串转换为一个 JSONObject,并没有将其映射为一个具体的 struct:如果想要获取值就需要先做断言将其转换为 map 或 ...
- Linux教我们丢掉键盘
前言 本篇博客并非博主编写,而是跟着黑马教程整理的. 因为Linux都是一些操作命令,也不想深入研究,所以就用此博客记录一下平时的基本知识,方便日后查找. 一.常用命令 命令 对应英文 作用 ls l ...
- mvc url重写
public class newDomainRoute : Route { private Regex domainRegex; private Regex pathRegex; public str ...
- 五分钟给你的 gRPC服务 加上 HTTP 接口
gRPC 服务要加 HTTP 接口? go-zero 给大家带来极简的 RESTful 和 gRPC 服务开发体验的同时,社区又给我们提出了新的期望: 我想只写一次代码 既要 gRPC 接口 也要 H ...