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 ...
随机推荐
- el表达式对js方法的传值
我常用于在jsp页面遍历集合和分页中的页面跳转事件. jsp: <!-- 引入jstl --> <%@ taglib prefix="c" uri="h ...
- Lib之过?Java反序列化漏洞通用利用分析
转http://blog.chaitin.com/ 1 背景 2 Java反序列化漏洞简介 3 利用Apache Commons Collections实现远程代码执行 4 漏洞利用实例 4.1 利用 ...
- 侯捷STL学习(四)--OOP-GP/操作符重载-泛化特化
C++标准库第二讲 体系结构与内核分析 第1-7节为第一讲 读源代码前的准备 第八节:源代码分布 C++基本语法 模板的使用 数据结构和算法 本课程主要使用:Gnu C 2.9.1与Gun C 4.9 ...
- Git命令之创建版本
安装 安装好Git后,将会在桌面生成 这样一个图标 运行后将会是类似控制台程序的黑色窗口,其中mingw64(参考百度百科).这样的话就可以在输入命令 例如 :git 见到下图有详细的用法表示成功否则 ...
- python web框架 Django进阶
django 进阶 基础中,一些操作都是手动创建连接的非主流操作,这样显得太low,当然也是为了熟悉这个框架! 实际中,django自带连接数据库和创建app的机制,同时还有更完善的路由系统机制.既然 ...
- 破解Mac版MyEclipse-2017-ci3 2017、11、21亲测有效
一.前提 要有安装好的jdk,没有的Mac用户看这篇博客:给Mac安装最新版本的jdk(戳此) Windows用户先去官网(戳此)下载jdk,然后百度”jdk配置环境变量”(戳此),很简单的,加油你 ...
- 装饰器api
import hashlib import time from django.http import HttpResponse key="qwrwertyuiop" visited ...
- 判断Integer值相等不能用==
今天在开发中判断两个Integer值相等, Integer a = 3; Duixiang duixiang = new Duixiang(); duixiang = DAO.getDuixiang( ...
- Navicat for Oracle中如何使用外键
转自:https://blog.csdn.net/weixin_39183543/article/details/80555104 1. 外键名最后保存的时候自动生成: 2. 参考模式自动生成: 3. ...
- UML在需求分析阶段的应用
转自:https://www.cnblogs.com/fuhaots2009/p/3430666.html 上一篇博客写了uml在软件开发过程中的应用,这以篇要详细介绍一下UML在需求分析过程中的应用 ...