Dynamic Rankings(整体二分)

带修区间第k小。\(n,q\le 10^4\)。

这次我们旧瓶装新酒,不用带修主席树。我们用整体二分!整体二分是啥东西呢?

二分答案可以解决一次询问的问题。只要二分这个询问的答案就行了。

考虑这道题,如果改成一个询问,怎么用二分答案做(虽然其它方法随便做)。把初始值也看成一个修改,暴力修改值。二分区间第k小数的值v,把小于v的数都改成1,大于的都改成0。那么现在问题就变成了,查询区间中1的个数cnt。如果cnt<=k,那么第k小数的值肯定<=v。否则第k小数的值>v。

对于这道题,如果把所有询问都二分一遍,那么时间复杂度为\(O(q*nlogv)\)。炸了!!

好的,我们来边缘ob一波。我们发现,我们把所有询问都二分答案了一遍。可不可以把询问放到一个二分里呢?

这就是整体二分。把所有修改和询问按照时间排在一起,设当前层二分的答案是v。那么,就可以把小于v的所有数变成1,大于v的则变成0。

那么,对于这个层的每一个询问,它们都需要获得它们[l, r]区间中1的个数。并且,还要支持修改某个位置的值(把那个值变成0或变成1)。用树状数组维护就行了哟。

显然时间复杂度是\(O(logv*nlogn)=O(nlog^2n)\)。但是比起带修主席树来说,整体二分的常数相对小一些,不过也快不了多少。

能用整体二分的条件是:

  • 询问满足可二分性
  • 修改对询问的贡献独立
  • 题目允许离线处理询问
  • ……

整体二分可以二分第k大值,也可以二分时间(某个点被消灭的时间)。

还有一个东西,我讲不清楚,摘一下这里的博客:

关于整体二分

整体二分主要是把所有询问放在一起二分答案,然后把操作也一起分治。

什么时候用呢?

当你发现多组询问可以离线的时候

当你发现询问可以二分答案而且check复杂度对于单组询问可以接受的时候

当你发现询问的操作都是一样的的时候

你就可以使用整体二分这个东西了。

具体做法讲起来有些玄学,其实类似主席树转化到区间的操作或者线段树上二分。

想想:二分答案的时候,对于一个答案,是不是有些操作是没用的,有些操作贡献是不变的?

比如二分一个时间,那么时间后面发生的操作就是没有用的,时间前面的贡献是不变的。

二分一个最大值,比mid大的都是没用的,比mid小的个数是一定的。

整体二分就是利用了这么一个性质。

坑点:

树状数组不能暴力清零!(\(O(n^2logn)\)预警)


#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn=5e4+5;
struct Query{
int x, y, k, type, dfn; //l, r, k, 2, 询问编号 或者修改时值
}q[maxn], q1[maxn], q2[maxn]; int a[maxn], n, m, t, cntq, ans[maxn]; int seg[maxn];
inline int lowbit(int x){ return x&(-x); }
void add(int x, int v){
for (int i=x; i<=n; i+=lowbit(i))
seg[i]+=v; }
int query(int x){ int re=0;
for (int i=x; i>0; i-=lowbit(i))
re+=seg[i]; return re; } void solve(int qb, int qe, int l, int r){
if (qb>qe) return;
if (l==r){
for (int i=qb; i<=qe; ++i)
if (q[i].type==2) ans[q[i].dfn]=l;
return; }
int m=(l+r)>>1, f=0, s=0; //f,s:左边/右边几个操作
//memset(seg, 0, sizeof(seg)); 这行的问题!
for (int i=qb; i<=qe; ++i){
if (q[i].type==1)
if (q[i].x<=m){
add(q[i].k, q[i].y);
q1[f++]=q[i];
} else q2[s++]=q[i];
else {
int t=query(q[i].y)-query(q[i].x-1); //区间中有多少1
if (t>=q[i].k) q1[f++]=q[i];
else{ q[i].k-=t; q2[s++]=q[i]; }
}
}
for (int i=0; i<f; ++i)
if (q1[i].type==1) add(q1[i].k, -q1[i].y);
//左边的修改对右边没影响,右边的修改对左边的也没影响
memcpy(q+qb, q1, f*sizeof(Query));
memcpy(q+qb+f, q2, s*sizeof(Query));
solve(qb, qb+f-1, l, m);
solve(qb+f, qe, m+1, r);
} int main(){
scanf("%d%d", &n, &m);
char c; int x, y, k, maxm=0;
for (int i=1; i<=n; ++i){
scanf("%d", &a[i]); maxm=max(maxm, a[i]);
q[++cntq]=(Query){a[i], 1, i, 1, cntq}; }
for (int i=1; i<=m; ++i){
while (c=getchar(), !isgraph(c));
scanf("%d%d", &x, &y); maxm=max(maxm, y);
if (c=='Q'){
scanf("%d", &k);
q[++cntq]=(Query){x, y, k, 2, cntq}; //询问区间[x, y],第k小数
}else{
q[++cntq]=(Query){a[x], -1, x, 1, cntq}; //由于只有a[x]<=m时,在前面会打标记,因此也在a[x]<=m时才消去
a[x]=y; //通过a[x]来判断修改要分到哪里
q[++cntq]=(Query){a[x], 1, x, 1, cntq}; //a[k]=x
}
}
solve(1, cntq, 0, maxm);
for (int i=1; i<=cntq; ++i)
if (ans[i]) printf("%d\n", ans[i]);
return 0;
}

Dynamic Rankings(整体二分)的更多相关文章

  1. [bzoj1901][zoj2112][Dynamic Rankings] (整体二分+树状数组 or 动态开点线段树 or 主席树)

    Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has ...

  2. 【BZOJ1901】Dynamic Rankings [整体二分]

    Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 给定一个含 ...

  3. BZOJ 1901 Zju2112 Dynamic Rankings ——整体二分

    [题目分析] 上次用树状数组套主席树做的,这次用整体二分去水. 把所有的查询的结果一起进行二分,思路很好. [代码] #include <cstdio> #include <cstr ...

  4. BZOJ1901: Zju2112 Dynamic Rankings(整体二分 树状数组)

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 9094  Solved: 3808[Submit][Status][Discuss] Descript ...

  5. ZOJ2112 Dynamic Rankings(整体二分)

    今天学习了一个奇技淫巧--整体二分.关于整体二分的一些理论性的东西,可以参见XRH的<浅谈数据结构题的几个非经典解法>.然后下面是一些个人的心得体会吧,写下来希望加深一下自己的理解,或者如 ...

  6. BZOJ 1901 Dynamic Rankings (整体二分+树状数组)

    题目大意:略 洛谷传送门 这道题在洛谷上数据比较强 貌似这个题比较常见的写法是树状数组套主席树,动态修改 我写的是整体二分 一开始的序列全都视为插入 对于修改操作,把它拆分成插入和删除两个操作 像$C ...

  7. 洛谷$P2617\ Dynamic\ Rankings$ 整体二分

    正解:整体二分 解题报告: 传送门$w$ 阿查询带修区间第$k$小不显然整体二分板子呗,,, 就考虑先按时间戳排序(,,,其实并不需要读入的时候就按着时间戳排的鸭$QwQ$ 每次二分出$mid$先把所 ...

  8. BZOJ.1901.Dynamic Rankings(整体二分)

    题目链接 BZOJ 洛谷 (以下是口胡) 对于多组的询问.修改,我们可以发现: 假设有对p1,p2,p3...的询问,在这之前有对p0的修改(比如+1),且p0<=p1,p2,p3...,那么我 ...

  9. ZOJ 2112 Dynamic Rankings(二分,树套树)

    动态区间询问kth,单点修改. 区间用线段树分解,线段树上每条线段存一颗平衡树. 不能直接得到kth,但是利用val和比val小的个数之间的单调性,二分值.log^3N. 修改则是一次logN*log ...

随机推荐

  1. 关于64位操作系统使用C#访问注册表失败的问题

    通过C#的注册表类 Registry.GetValue 进行访问时,其返回值一直为空.然后认真检查检查再检查了注册表路径,发现路径没有一点问题,不说废话,上代码: if (Registry.GetVa ...

  2. 发任务找不到test-unit报错

    发任务的时候因找不到gem包test-unit报错, 出错行: require 'test/unit' require 'test/unit/testresult' 解决办法如下 1.通过命令查看ge ...

  3. phonegap 解决https访问问题

    ios报错 在AppDelegate.m文件在最后加入(在@end后面加空行): @implementation NSURLRequest(DataController) + (BOOL)allows ...

  4. 实验吧CTF题库-密码学(部分)

    这里没有key: 打开链接,有一个弹窗 然后就是一个空白网页,右键查看源代码 这里有一串js密文,解密一下,https://www.dheart.net/decode/index.php 得到flag ...

  5. 将chrome浏览器的默认背景颜色修改为浅绿色,以减缓长时间看电脑的眼睛不舒服的问题

    修改chrome文件夹中的Custom.css, 此文件里面默认内容是空的. 在其中添加下面这段代码: 你也可以选择自己的喜欢的颜色, 前提是你知道你想要更改的颜色的十六进制颜色值, 例如:#CCEB ...

  6. 2015.1.15 利用Oracle函数插入表结构 Bulk collect into 不用循环,简洁高效

    如果表结构只对应一个字段,可以 select col1 bulk collect into 变量,不用游标循环,简洁高效 create or replace function get_airway_s ...

  7. Oracle、SqlServer——临时表

    一.oracle 1.概述: oracle数据库的临时表的特点: 临时表默认保存在TEMP中: 表结构一直存在,直到删除:即创建一次,永久使用: 不支持主外键. 可以索引临时表和在临时表基础上建立视图 ...

  8. select 动态添加option函数

    转自:https://lym6520.iteye.com/blog/309937 经常会用到select动态添加元素,写了个方法,方便调用!  ... /** * 功能:select对象动态添加Opt ...

  9. javascript删除option选项的多种方法总结

    转自:https://blog.csdn.net/xiaoxuanyunmeng/article/details/16886505 1. JavaScript 代码如下: var oSel=docum ...

  10. H.264学习笔记

    1.帧和场的概念 视频的一场或一帧可用来产生一个编码图像.通常,视频帧可以分成两种类型:连续或隔行视频帧.我们平常看的电视是每秒25帧,即每秒更换25个图像,由于视觉暂留效应,所以人眼不会感到闪烁.每 ...