首页 > 其他分享 >【DS】浅谈树状数组倍增

【DS】浅谈树状数组倍增

时间:2022-08-18 20:11:51浏览次数:100  
标签:浅谈 树状 int sum tot 枚举 数组 DS

无意中看到的一个小 trick,便记录下来。

引入

给您一个数组,您需要实现以下操作和询问:

\(\bullet\) 插入一个数字 \(x\)。

\(\bullet\) 查询排名为 \(k\) 的数 \(x\)。

显然我们有权值线段树或者平衡树的做法。
但是我偏不(傲娇),我们来考虑树状数组怎么做。

树状数组倍增

定义:

\(n\):数组大小

\(a_i\):离散化后第 \(i\) 个数出现的次数

\(c_i\):树状数组

思路

插入一个数字就是单点修改啦,考虑询问。

写过平衡树模板的我们肯定知道,一个数 \(x\) (离散化后)的排名就是比 \(x\) 小的数的个数 \(+1\),即 \(\operatorname{rank}(x)=(\sum\limits^{x-1}_{i=1}a_i)+1\) 。那么反过来,要查询排名为 \(k\) 的数 \(x\), 它的位置就是 \(\max\limits_{\operatorname{rank}(x)\leq k}x\),我们把它展开来看,即

\[(\sum^{x-1}_{i=1}a_i)+1\leq k \]

\[(\sum^{x-1}_{i=1}a_i)\leq k-1 \]

左半部分可以直接树状数组求,我们枚举一个 \(r\),那么我们枚举到的符合条件的最大的 \(r\) 就是 \((x-1)\),答案即为 \(r+1\)。

为什么不能直接 \(\leq k\)?因为有的数可能不存在,例如 \(a=\{1,0, 1, 0, 0\}\) ,我们查询排名为 \(2\) 的数,按正确的方法答案就是 \(3\),如果直接 \(\leq k\) 则输出为 \(5\)。不过有的时候我们会需要这样做,在后文会讲到。

如何求 \(r\)?显然不能 \(O(n\log{n})\),那有没有什么方法能降低枚举复杂度至 \(O(\log{n})\) 呢?

废话,看标题不就知道了

具体实现

引理

\[c_i=\sum\limits^{i}_{j=i-lowbit(i)+1}a_i \]

由树状数组的定义知显然。

倍增

我们能不能通过枚举跳 \(2^{\log n}, 2^{\log n-1}, ... , 2^1, 2^0\) 的距离去找呢?

代码如下:

int kth(int k){
    int r=0,tot=0,x,y;
    for(int i=log(值域);~i;--i){
        x=r+(1<<i);if(x>值域)continue;
        y=tot+c[x];
        if(y<k)r=x,tot=y;
    }
    return r+1;
}

这里每次 \(tot\leftarrow tot+c_{r+2^i}\) 是什么意思呢?根据上面得引理可知,加上 \(c_{r+2^i}\) 相当于加上 $\sum\limits{r+2i}_{j=r}a_i $,即不断地向后拓展,到最后 \(tot\) 的值即为 \(\sum\limits^{r}_{i=1}a_i\)。

为什么这样就能满足 \(r\) 最大?因为我们是从大到小枚举的。

优点 & 缺点

\(\bullet\) 优点:常数小,码量小,容易记。

\(\bullet\) 缺点:需要离线。

用途

一般用于优化部分需要求 \(k\) 小的操作,不作为主要算法。

例题

\(\circ\) CF786C Till I Collapse

题意:将 \(n\) 个数划分成 \(m\) 段使得每中不同数字的个数 \(\le k\),对于每个 \(k\) 满足 \(1\le k \le n\) ,求出最小的 \(m\)。

考虑对于一个 \(k\) 怎么求。我们贪心地尽可能分最大的段,使得段内不同数字个数不大于 \(k\),询问区间不同数字的个数,就是数颜色嘛,我们想到 HH 的项链 的做法,但是有点不同:对于 HH 的项链里,我们知道右端点的位置,于是对于每一个数字的贡献都放到尽可能右边;但是这道题里面我们并不止都右端点(而是要求它),所以对于每一个枚举到的左端点的数字,(如果它对答案有贡献)我们计算贡献之后将它的贡献放到下一个出现的位置上就行了。每一次分段询问最远能到达的右端点即可,我们有这样的代码:

void add(int x,int v){while(x<=n)c[x]+=v,x+=lb;}
int kth(int k){
    int r=0,tot=0,x,y;
    ++k;//注意这里 k 要加一
    for(int i=18;~i;--i){
        x=r+(1<<i);if(x>n)continue;
        y=tot+c[x];
        if(y<k)r=x,tot=y;
    }
    return r;//注意这里 r 不用加一
}

for(int l=1,r=0;l<=n;++l){
    if(l==r+1)++ans,r=kth(l);
    add(l,-1),add(nxt[l],1);
}

为什么 \(k\) 要加一而 \(r\) 不用加一?因为我们计算数字个数的时候,中间可能有一串 \(0\),例如:\(a=\{1,1, 0, 1, 0, 0, 1, 0\}\),\(k=3\)。如果是之前的代码的话,返回的答案是 \(4\),而实际上能扩展到的最远的右端点是 \(6\)。我们把 \(k\) 加一并且 \(r\) 不加一就可避免此问题。

对于 \(1\) 到 \(n\) 的所有 \(k\) 怎么求?我们可以一起求啊!毕竟每个数的贡献仅在数本身,我们对于所有询问的左端点维护个优先队列,然后按照上面的方法计算答案即可。

提交记录

其他练习:

\(\circ\) CF1181D Irrigation

\(\circ\) Luogu P6619 [省选联考 2020 A/B 卷] 冰火战士

标签:浅谈,树状,int,sum,tot,枚举,数组,DS
From: https://www.cnblogs.com/RuntimeErr/p/16599951.html

相关文章

  • Python list methods All In One
    PythonlistmethodsAllInOnePython3#!/usr/bin/envpython3#coding=utf-8__author__='xgqfrms'__editor__='vscode'__version__='1.0.1'__copyrigh......
  • pytest系列——pytest_collection_modifyitems钩子函数修复参数化使用ids当测试用例描
    当我们对测试用例进行参数化时,使用@pytest.mark.parametrize的ids参数自定义测试用例的标题,当标题中有中文时,控制台和测试报告中会出现Unicode编码问题,这看起来特别像乱码,......
  • 文本编辑器MarkMyWords
    MarkMyWords是一款提供实时预览格式化的文章或预览HTML代码等功能的文本编辑器,可以帮助大家在无干扰模式下进行文本编辑,提高大家工作时的专注力。MarkMyWords为大家提供了......
  • openssh-浅谈openssl和openssh的升级
    最近项目上有服务器漏洞被扫描出来,是关于openssl的之前没怎么关注过这个问题,于是着手去了解了以下发现有些坑,分享下自己的经验。中间过程比较长,想省事的直接跳到第四节,......
  • 【AGC】publishing api contentRating in cds serviceAttr is invalid问题分析
    ​ 【问题背景】最近想通过华为AppGalleryConnect提供的publishingapi来向华为应用市场上传软件包,我按照官网文档的指导来依次调用相关接口设置我的应用:https://devel......
  • Dsu on tree
    Dsuontree代指树上启发式合并,并非是并查集个人觉得这个算法的思想跟莫队有些许相似,但是又利用了树链剖分的一些性质,从而使得复杂度大大降低,优秀的o(nlgn)。需要的前......
  • List<? extends T>与List<? super T>的区别
    往期热门文章:1、SpringBatch批处理,骚气还强大!2、CTO强烈禁止使用Calendar,那用啥?3、我,40岁码农,还在荷兰写低级代码,不敢回国…4、我的mybatis-plus用法,被全公司同事开......
  • Codeforces Round 81 Same GCDs
    SameGCDs原文题意:给定a,m求x在\([0,m)\)中有多少数字满足\(gcd(a,m)=gcd(a+x,m)\)思路:我们令\(g=gcd(a,m)\)那么\(a=k_1g\),\(m=k_2g\),且\(gcd(k_1,k_2......
  • MapAndSet
    Map1.Map它是一个双列集合和Collection集合是一种并列关系2.Map中的Key和Value是一一映射关系3.Map中的key和value都可以存储null值4.......
  • ENVI中基于SuperView-1立体像对数据提取DSM和点云数据
    ENVI5.4的摄影测量扩展模块(原正射校正扩展模块)增加了两个工具,分别为:GeneratePointCloudsandDSMbyDenseImageMatching——利用高重叠度的多景图像(例如立体像对)提......