P2617 Dynamic Rankings 解题报告
整体二分是一种东西,比如上面这道题。
先考虑一个不带修版本的,也就是经典问题区间 kth,显然我们可以主席树但是我知道你很想用主席树但是你先别用不用主席树,用一种离线的算法,叫整体二分。
首先先考虑处理单个询问,二分,简单吗?真简单,先二分一个 \(mid\),然后把区间内所有小于等于 \(mid\) 的数字丢进一个权值树状数组里,统计一下这些数字有多少个,就可以判定了。那么这个时候时间复杂度应该是 \(O((r - l + 1) \log_2 SIZE^2)\) 的(权值树状数组与二分带两只 log)。离散化就可以做到 \(O((r - l + 1)\log_2 (r - l + 1)^2)\),但一般没必要这么做(懒捏┓( ´∀` )┏)
我们学会了对一个询问这么做,那么多个询问呢?不难想到我们可以先二分一个 \(mid\),然后对于答案小于等于 \(mid\) 的询问,丢到一块,对于答案大于 \(mid\) 的询问也丢到一块。然后两块分别递归处理。
然后你就会发现你被骗了其实这样做是不行的,因为如果我们只把询问丢到一块,那么我们怎么更新元素呢?我们一个一个一个一个的扫描长度为 \(n\) 的数组 \(a\),然后将 \(a[i]\le mid\) 的元素丢到左半边,\(a[i]>mid\) 的丢到右半边?没必要啊!我们完全可以把初始序列看成 \(n\) 次对 \(i\) 位置添加一个权值为 \(a[i]\) 的操作。然后你就会发现,我们也应该一并把 \(a[i]\le mid\) 的添加操作丢到左半边,\(a[i] > mid\) 操作丢到右半边。
由于我语文太烂了,所以看不懂上面的很正常 QAQ简单来说,整体二分就是每次二分一个 \(mid\),然后将答案小于等于 \(mid\) 与会让答案小于等于 \(mid\) 的操作一块丢到左边,答案大于 \(mid\) 的查询和会让答案大于 \(mid\) 的操作丢到右边。这样就好啦(*^▽^*)。
这就是伟大的整体二分算法,是不是相当简单?总的来说,就是每次二分一个值,普通的二分是,如果只有一个询问,我们就把它划分,然后继续二分。整体二分,就是每次二分出来一个值,然后都得对一串进行划分。
这个东西出现在了 2013 年国家集训队论文里面,是许昊然这个巨佬讲的,所以建议直接看这篇文章反正他写的比我这个大蒟蒻写的好 1145141919810 倍我写这个就是给自己看的我有的时候都看不懂自己在写什么,比如语文考试的作文 QAQ。这篇文章里,谈到了整体二分的 5 个应用前提:
- 询问的答案具有可二分性。
- 修改对判定答案的贡献互相独立,修改之间互不影响效果
- 修改如果对判定答案有贡献,则贡献为一确定的与判定标准无关的值
- 贡献满足交换律、结合律,具有可加性
- 题目允许离线算法
以上出自许昊然巨佬论文的原文。第一点显而易见,不然你怎么整体二分。第五点也很显然,因为整体二分就是把所有操作放在一块处理,不能离线怎么放在一块。第二点为什么要“互相独立”呢?假设你的修改是“修改了 p 后才能修改 q”或者“修改了 p 就不能修改 q”这个时候就很不可做。大部分 DS 题都是修改之间互不影响效果的吧 qwq。第三点也很简单,就是说我们修改了后,判定还是照样的判定方法。拿上面这题举例子,刚开始的加数我们看成修改,显而易见,修改是修改了,但是我们判定就是小于等于 \(mid\),是不会有影响的。第四点也不难理解,拿上面那题举例子,每个点的贡献就是如果这个点小于等于 \(mid\),就会贡献一个 \(1\),满足交换律,结合律(你先更新哪个点后更新哪个点都一样),同时显而易见具有可加性。
回到动态区间 kth 来,不难发现,为了独立每个修改的贡献,我们完全可以把单点修改拆成“删除原来的值”和“加入更新的值”,如此一来这样贡献就能独立了。
删除原来的值和上面讨论过的“加入更新的值”就反着来就好了吧,还是很简单的说 awa
#include <iostream>
#include <cstring>
#define MAXN 200000
using namespace std;
int tr[MAXN + 10], n, m, tot;
int lowbit(int x) {return (x & (-x));}
void add(int pos, int val) {
for(; pos <= n; pos += lowbit(pos))
tr[pos] += val;
}
int query(int pos) {
int rest = 0;
while(pos) {
rest += tr[pos];
pos -= lowbit(pos);
}
return rest;
}
//type = 0 query
//type = 1 insert
//type = 2 delete
struct node {
int type, val, l, r, ind;
//For type = 0
//[l, r] val ind = i
//For type = 1/2
// l val ind = i
} Q[MAXN * 2 + 10], qa[MAXN * 2 + 10], qb[MAXN * 2 + 10];
int ans[MAXN + 10], a[MAXN + 10];
void twofen(int l, int r, int s, int t) {
if(l > r) return ;
if(s == t) {
for(int p = l; p <= r; p++)
if(!Q[p].type)
ans[Q[p].ind] = s;
return ;
}
int mid = (s + t) >> 1, ta = 0, tb = 0;
for(int p = l; p <= r; p++) {
if(Q[p].type == 0) {
int qr = query(Q[p].r) - query(Q[p].l - 1);
if(qr >= Q[p].val) qa[++ta] = Q[p];
else Q[p].val -= qr, qb[++tb] = Q[p];
}
else if(Q[p].type == 1) {
if(Q[p].val <= mid) add(Q[p].l, 1), qa[++ta] = Q[p];
else qb[++tb] = Q[p];
}
else if(Q[p].type == 2) {
if(Q[p].val <= mid) add(Q[p].l, -1), qa[++ta] = Q[p];
else qb[++tb] = Q[p];
}
}
for(int p = l; p <= r; p++)
if(Q[p].val <= mid)
if(Q[p].type == 1) add(Q[p].l, -1);
else if(Q[p].type == 2) add(Q[p].l, 1);
for(int p = l, i = 1; i <= ta; p++, i++) Q[p] = qa[i];
for(int p = l + ta, i = 1; i <= tb; p++, i++) Q[p] = qb[i];
twofen(l, l + ta - 1, s, mid);
twofen(l + ta, r, mid + 1, t);
}
int main() {
freopen("read.txt", "r", stdin);
freopen("write.txt", "w", stdout);
cin >> n >> m;
for(int p = 1; p <= n; p++) {
tot++;
cin >> a[p], Q[tot].val = a[p];
Q[tot].type = 1, Q[tot].l = p;
}
char opt;
int qt = 0;
for(int p = 1; p <= m; p++) {
cin >> opt;
if(opt == 'Q') {
tot++;
cin >> Q[tot].l >> Q[tot].r >> Q[tot].val;
Q[tot].ind = ++qt, Q[tot].type = 0;
}
else {
int rt, rest; tot++;
cin >> rt >> rest;
Q[tot].l = rt;
Q[tot].val = a[rt];//这里一直写成 a[p] 调了好久,太菜了 QAQ
Q[tot].type = 2;
tot++;
Q[tot].l = rt, Q[tot].val = rest;
Q[tot].type = 1, a[rt] = rest;
}
}
twofen(1, tot, 0, 1e9);
for(int p = 1; p <= qt; p++)
cout << ans[p] << endl;
}
P2617 Dynamic Rankings 解题报告的更多相关文章
- 洛谷 P2617 Dynamic Rankings 解题报告
P2617 Dynamic Rankings 题目描述 给定一个含有\(n\)个数的序列\(a[1],a[2],a[3],\dots,a[n]\),程序必须回答这样的询问:对于给定的\(i,j,k\) ...
- P2617 Dynamic Rankings(树状数组套主席树)
P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...
- 2018.07.01洛谷P2617 Dynamic Rankings(带修主席树)
P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i ...
- 洛谷P2617 Dynamic Rankings (主席树)
洛谷P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a ...
- 【学习笔鸡】整体二分(P2617 Dynamic Rankings)
[学习笔鸡]整体二分(P2617 Dynamic Rankings) 可以解决一些需要树套树才能解决的问题,但要求询问可以离线. 首先要找到一个具有可二分性的东西,比如区间\(k\)大,就很具有二分性 ...
- 洛谷$P2617\ Dynamic\ Rankings$ 整体二分
正解:整体二分 解题报告: 传送门$w$ 阿查询带修区间第$k$小不显然整体二分板子呗,,, 就考虑先按时间戳排序(,,,其实并不需要读入的时候就按着时间戳排的鸭$QwQ$ 每次二分出$mid$先把所 ...
- P2617 Dynamic Rankings(待修改区间第k大)
题目链接:https://www.luogu.org/problemnew/show/P2617 题目: 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的 ...
- luogu P2617 Dynamic Rankings && bzoj 1901 (带修改区间第k大)
链接:https://www.luogu.org/problemnew/show/P2617 思路: 如果直接在主席树上修改的话,每次修改都会对后面所有的树造成影响,一次修改的复杂度就会变成 : n* ...
- SP8791 DYNALCA - Dynamic LCA 解题报告
SP8791 DYNALCA - Dynamic LCA 有一个森林最初由 \(n (1 \le n \le 100000)\) 个互不相连的点构成 你需要处理以下操作: link A B:添加从顶点 ...
- LUOGU P2617 Dynamic Rankings(树状数组套主席树)
传送门 解题思路 动态区间第\(k\)大,树状数组套主席树模板.树状数组的每个位置的意思的是每棵主席树的根,维护的是一个前缀和.然后询问的时候\(log\)个点一起做前缀和,一起移动.时空复杂度\(O ...
随机推荐
- MISC中需要jio本处理的奇怪隐写
好耶! 老样子,还是以ctfshow[1]中misc入门中的题目为切入点 感兴趣的同学可以一边做题一边看看.呜呜,求点浏览量了 APNG隐写(MISC40) APNG是普通png图片的升级版,他的后缀 ...
- Blazor和Vue对比学习(进阶.路由导航一):基本使用
Blazor和Vue都是单文件组件SPA,路由的实现逻辑非常相似,页面路径的改变都是组件的切换,但因为各自语言的特性,在实现方式上有较大差异. 一.安装 1.Vue:Router是Vue的一个插件.如 ...
- CORS与CSRF在Spring Security中的使用
背景 在项目使用了Spring Security之后,很多接口无法访问了,从浏览器的网络调试窗看到的是CORS的报错和403的报错 分析 我们先来看一下CORS是什么,和它很相似的CSRF是什么,在S ...
- base64解析爬取糗百
一.缘由 这是我之前刚开始学习的时候爬取糗百的练习内容,主要练习的是bs64解析.虽然现在用的不是特别的多,但是当初的时候用起来还是非常的顺手的. 二.代码实现 #coding:utf-8 impor ...
- 大数据-业务数据采集-FlinkCDC
CDC CDC 是 Change Data Capture(变更数据获取)的简称.核心思想是,监测并捕获数据库的变动(包括数据或数据表的插入.更新以及删除等),将这些变更按发生的顺序完整记录下来,写入 ...
- MySQL空间暴涨150G导致锁定,发生了什么
背景 12月1号中午突然收到大量报警,某客户环境操作数据库大量失败,报错信息如下图所示: 这个报错我是第一次见,一时间有点无所适从,但是从字面意思来看是MySQL目前处于LOCK_WRITE_GROW ...
- tcp/udp 协议特性和三次握手
一.TCP/UDP协议特性1)TCP特性:工作在传输层.建立连接.可靠的.错误检查 2)UDP特性:工作在传输层.不需要连接.不可靠的.有限的错误检查.传输性能高 2.控制位及确认号解释 控制位:由6 ...
- IdentityServer4的最佳使用
简介 本人做微服务项目也有一段时间了,在微服务中让我感触颇深的就是这个IdentityServer4了,ID4(IdentityServer4的简称)中涉及的概念颇多,本文不谈概念(我怕读者没耐心 ...
- JAVA中生成随机数Random VS ThreadLocalRandom性能比较
前言 大家项目中如果有生成随机数的需求,我想大多都会选择使用Random来实现,它内部使用了CAS来实现. 实际上,JDK1.7之后,提供了另外一个生成随机数的类ThreadLocalRandom,那 ...
- python基础(数据库、可视化软件Navicat、python操作MySQL)
多表查询的两种方法 数据准备: 建表 create table dep( id int primary key auto_increment, name varchar(20) ); create t ...