树状数组

原始问题

  1. \(a_x \overset+\gets y\)
  2. \(\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)

这个方法我暂时没有找到严格的数学证明,这里给一张图。

(贺的)

前缀修改,单点查询

  1. \(\forall i \in [1, R],a_i \overset+\gets y\)
  2. \(a_x\)

通过差分,可以轻松解决。

multiset 个数查询

  1. 删除一个 \([1, R]\)
  2. 加入一个 \([1, R]\)
  3. 求 \(x\) 在集合中出现了多少次

建立一个桶数组,删除就是 \(\forall i \in [1, R],a_i \overset-\gets 1\),加入就是 \(\forall i \in [1, R],a_i \overset+\gets 1\),于是转化为前缀修改,单点查询。有时需要离散化。这种方法叫做 权值树状数组

动态 multiset 第 \(K\) 小

  1. 加入一个 \(x\)
  2. 删除一个 \(x\)
  3. 求集合第 \(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\) 的个数),通过建立第一维的顺序可以求二维偏序。

前缀修改,前缀查询

  1. \(\forall i \in [1, R],a_i \overset+\gets y\)
  2. \(\sum\limits_{i=1}^{r} a_i\)

考虑差分。题目变为

  1. \(a_i \overset+\gets y\)
  2. \(\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

  1. \(\forall i \in [1, R],a_i \overset+\gets y\)
  2. \(\sum\limits_{i=1}^{r} \sum\limits_{j=1}^{i} a_j\)

考虑差分。题目变为

  1. \(a_i \overset+\gets y\)
  2. \(\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的更多相关文章

  1. 创建Azure DS 虚拟机并附加SSD硬盘

    $subscriptionName = "Windows Azure Enterprise Trial" #订阅名称 $location = "China East&qu ...

  2. DS实验题 融合软泥怪-2 Heap实现

    题目和STL实现:DS实验题 融合软泥怪-1 用堆实现优先队列 引言和堆的介绍摘自:Priority Queue(Heaps)--优先队列(堆) 引言: 优先队列是一个至少能够提供插入(Insert) ...

  3. Hyper-V 2012 R2 故障转移群集之建立域控(AD DS)与加入域

    Windows  2012 R2建立域控(AD DS)与加入域 Active Directory概述:          使用 Active Directory(R) 域服务 (AD DS) 服务器角 ...

  4. dataGridViewX和数据库的链接之dataGridViewX1.DataSource = ds.Tables[0];

    dataGridViewX1.DataSource = ds.Tables[0]; 1, dataGridViewX和数据库链接,如果我们用 dataGridViewX1.DataSource = d ...

  5. Windows Azure Virtual Machine (26) 使用高级存储(SSD)和DS系列VM

    <Windows Azure Platform 系列文章目录> Update: 2016-11-3,如果大家在使用Linux VM,使用FIO进行IOPS测试的时候,请使用以下命令: su ...

  6. DS Tree 已知后序、中序 => 建树 => 求先序

    注意点: 和上一篇的DS Tree 已知先序.中序 => 建树 => 求后序差不多,注意的地方是在aftorder中找根节点的时候,是从右往左找,因此递归的时候注意参数,最好是拿纸和笔模拟 ...

  7. [DS Basics] Data structures

    1, LinkedList composed of one and one Node: [data][next]. [head] -> [data][next] -> [data][nex ...

  8. DS实验题 Old_Driver UnionFindSet结构 指针实现邻接表存储

    题目见前文:DS实验题 Old_Driver UnionFindSet结构 这里使用邻接表存储敌人之间的关系,邻接表用指针实现: // // main.cpp // Old_Driver3 // // ...

  9. DS实验题 Dijkstra算法

    参考:Dijkstra算法 数据结构来到了图论这一章节,网络中的路由算法基本都和图论相关.于是在拿到DS的实验题的时候,决定看下久负盛名的Dijkstra算法. Dijkstra的经典应用是开放最短路 ...

  10. 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 ...

随机推荐

  1. Redis实现延迟队列的正确姿势

    在之前探讨延时队列的文章中我们提到了 redisson delayqueue 使用 redis 的有序集合结构实现延时队列,遗憾的是 go 语言社区中并无类似的库.不过问题不大,没有轮子我们自己造. ...

  2. JavaScript中DOM查询封装函数

    在JavaScript中可以通过BOM查询html文档中的元素,也就是所谓的在html中获取对象然后对它添加一个函数. 常用的方法有以下几种: ①document.getElementById() 通 ...

  3. JavaScript做简单的购物车效果(增、删、改、查、克隆)

    比如有时候遇到下面这种情况,点击加入购物车,然后在上方的购物车中动态的添加商品以及商品的信息,我们就可以通过JavaScript实现简单的这些操作. 首先我们需要在html文档中,通过css对页面的布 ...

  4. wcf .net webService和 .net webApi的联系与差异

    首先,我们需要清楚它们的概念,然后才能走好下一步. wcf是对于ASMX,.Net Remoting,Enterprise Service,WSE,MSMQ等技术的整合,它是一种重量级消息交互框架,广 ...

  5. 520到了,作为一个python程序员,必须整点肤白貌美的爬虫代码给你们~

    马上520就快到啦~ 整点好看的给你们看下~ 直接开搞~ 代码流程 模拟浏览器向服务器发送一个http请求,网站接收到请求后返回数据.在写爬虫代码的时候一定先要去模拟浏览器访问,因为现在的网站当接收到 ...

  6. idea 在创建maven时没有src的解决方法

    在创建maven时    加上archetypeCatalog=internal

  7. 用面向对象的方式操作 JSON 甚至还能做四则运算 JSON 库

    前言 在之前实现的 JSON 解析器中当时只实现了将一个 JSON 字符串转换为一个 JSONObject,并没有将其映射为一个具体的 struct:如果想要获取值就需要先做断言将其转换为 map 或 ...

  8. Linux教我们丢掉键盘

    前言 本篇博客并非博主编写,而是跟着黑马教程整理的. 因为Linux都是一些操作命令,也不想深入研究,所以就用此博客记录一下平时的基本知识,方便日后查找. 一.常用命令 命令 对应英文 作用 ls l ...

  9. mvc url重写

    public class newDomainRoute : Route { private Regex domainRegex; private Regex pathRegex; public str ...

  10. 五分钟给你的 gRPC服务 加上 HTTP 接口

    gRPC 服务要加 HTTP 接口? go-zero 给大家带来极简的 RESTful 和 gRPC 服务开发体验的同时,社区又给我们提出了新的期望: 我想只写一次代码 既要 gRPC 接口 也要 H ...