Dynamic Rankings(整体二分)
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(整体二分)的更多相关文章
- [bzoj1901][zoj2112][Dynamic Rankings] (整体二分+树状数组 or 动态开点线段树 or 主席树)
Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings has ...
- 【BZOJ1901】Dynamic Rankings [整体二分]
Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 给定一个含 ...
- BZOJ 1901 Zju2112 Dynamic Rankings ——整体二分
[题目分析] 上次用树状数组套主席树做的,这次用整体二分去水. 把所有的查询的结果一起进行二分,思路很好. [代码] #include <cstdio> #include <cstr ...
- BZOJ1901: Zju2112 Dynamic Rankings(整体二分 树状数组)
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 9094 Solved: 3808[Submit][Status][Discuss] Descript ...
- ZOJ2112 Dynamic Rankings(整体二分)
今天学习了一个奇技淫巧--整体二分.关于整体二分的一些理论性的东西,可以参见XRH的<浅谈数据结构题的几个非经典解法>.然后下面是一些个人的心得体会吧,写下来希望加深一下自己的理解,或者如 ...
- BZOJ 1901 Dynamic Rankings (整体二分+树状数组)
题目大意:略 洛谷传送门 这道题在洛谷上数据比较强 貌似这个题比较常见的写法是树状数组套主席树,动态修改 我写的是整体二分 一开始的序列全都视为插入 对于修改操作,把它拆分成插入和删除两个操作 像$C ...
- 洛谷$P2617\ Dynamic\ Rankings$ 整体二分
正解:整体二分 解题报告: 传送门$w$ 阿查询带修区间第$k$小不显然整体二分板子呗,,, 就考虑先按时间戳排序(,,,其实并不需要读入的时候就按着时间戳排的鸭$QwQ$ 每次二分出$mid$先把所 ...
- BZOJ.1901.Dynamic Rankings(整体二分)
题目链接 BZOJ 洛谷 (以下是口胡) 对于多组的询问.修改,我们可以发现: 假设有对p1,p2,p3...的询问,在这之前有对p0的修改(比如+1),且p0<=p1,p2,p3...,那么我 ...
- ZOJ 2112 Dynamic Rankings(二分,树套树)
动态区间询问kth,单点修改. 区间用线段树分解,线段树上每条线段存一颗平衡树. 不能直接得到kth,但是利用val和比val小的个数之间的单调性,二分值.log^3N. 修改则是一次logN*log ...
随机推荐
- HTML 5中的结构元素
1.header:标记头部区域的内容 .footer:标记页脚区域的内容 .section:Web页面中的一块区域 4.article:独立的文章内容区域 5.aside:相关侧边内容或者引文区域 6 ...
- iOS离屏渲染
为什么会使用离屏渲染 当使用圆角,阴影,遮罩的时候,图层属性的混合体被指定为在未预合成之前不能直接在屏幕中绘制,所以就需要屏幕外渲染被唤起. 屏幕外渲染并不意味着软件绘制,但是它意味着图层必须在被显示 ...
- 蓝牙服务 UUID
https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx 手机蓝牙对手机 ,华为平板取红米手机 8 个Audio So ...
- 部署和调优 1.3 pureftp部署和优化-2
登录ftp,用远程的一台机器,执行 lftp 如果没有这个命令,需要安装 yum install -y lftp 登录ftp lftp ftpuser1@192.168.1.117 输入口令,即密码 ...
- DAY11-MYSQL数据操作
一 介绍 MySQL数据操作: DML ======================================================== 在MySQL管理软件中,可以通过SQL语句中的 ...
- Android LRUCache
package android.util; import java.util.LinkedHashMap; import java.util.Map; /** * A cache that holds ...
- JavaScript的运算符
一.什么是表达式??? 是ECMScript中的一个短语,解释器可以通过计算把它转成一个值,最简单的表达式是字面量或者变量名,单一字面量和组合字面量统称为表达式. 二.一元运算符 1.delete 运 ...
- JAVA基础知识总结11(异常)
异常: 就是不正常.程序在运行时出现的不正常情况.其实就是程序中出现的问题.这个问题按照面向对象思想进行描述,并封装成了对象.因为问题的产生有产生的原因.有问题的名称.有问题的描述等多个属性信息存在. ...
- android中音频播放的两种方法
方法1.通过MediaPlayer播放,可播放本地,网络音频,适合播放单个文件 方法2.通过SoundPool,适合播放多个文件 详见:http://www.cnblogs.com/xiaoQLu/a ...
- 详解CSS盒模型(转)
详解CSS盒模型 阅读目录 一些基本概念 盒模型 原文地址:http://luopq.com/2015/10/26/CSS-Box-Model/ 本文主要是学习CSS盒模型的笔记,总结了一些基本概 ...