静态区间第K小(整体二分、主席树)
题目链接
题解
主席树入门题
但是这里给出整体二分解法
整体二分顾名思义是把所有操作放在一起二分
想想,如果求\([1-n]\)的第\(k\)小怎么二分求得?
我们可以二分答案\(k\), \(O(n)\)统计有多少个数小于等于\(k\)
如果对于每个询问都这么搞,肯定不行
我们可以发现,如果每次都搞一次,有许多算重复的地方
\(div(l, r, st, ed)\)表示\(k\)二分的区间\([l-r]\), 对应操作答案区间在\([st-ed]\)
(如果没看懂,先往下看。)
\(mid = (l+r)/2\)
对于每次的\(mid\), 我们把对\(k\)往左移还有贡献的 放在一起, 右移的放在一起,这样答案就在一个区间内
那么如何统计一段区间有多少个数比\(k\)大呢?
我们开一个树状数组,如果\(x\)位上的数大于\(k\),那么给\(x\)加上1
然后统计就是区间求和了
Code
#include<bits/stdc++.h>
#define LL long long
#define RG register
using namespace std;
const int N = 200010, INF = 1e9;
struct rec {
int op, x, y, z;
}q[N<<1], lq[N<<1], rq[N<<1];
int n, m, tot, c[N], ans[N];
#define lowbit(x) (x&(-x))
void add(int x, int v) {
while (x <= n) c[x] += v, x += lowbit(x);
return ;
}
int sum(int x) {
int res = 0;
while (x > 0) res += c[x], x -= lowbit(x);
return res;
}
int X[N], cnt;
inline int gi() {
RG int x = 0; RG char c = getchar(); bool f = 0;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') c = getchar(), f = 1;
while (c >= '0' && c <= '9') x = x*10+c-'0', c = getchar();
return f ? -x : x;
}
void div(int l, int r, int st, int ed) {
if (st > ed) return ;//[l~r]中没有答案
if (l == r) {
for (int i = st; i <= ed; i++)
if (q[i].op) ans[q[i].op] = l;//记录答案
return ;
}
int mid = (l + r) >> 1;
int lt = 0, rt = 0;
for (int i = st; i <= ed; i++) {
if (!q[i].op) {
if (q[i].y <= mid) add(q[i].x, 1), lq[++lt] = q[i];//k如果往左移,修改操作还有影响
else rq[++rt] = q[i];
}
else {
int res = sum(q[i].y) - sum(q[i].x-1);
if (res >= q[i].z) lq[++lt] = q[i];//已经满足至少第K大了,K还可以调小
else q[i].z -= res, /*把所有q[i].y<=mid的贡献减去,调大k时就不需要统计这些的贡献了*/rq[++rt] = q[i];
}
}
for (int i = st; i <= ed; i++)
if (!q[i].op && q[i].y <= mid) add(q[i].x, -1);//清除
for (int i = 1; i <= lt; i++) q[st+i-1] = lq[i];
for (int i = 1; i <= rt; i++) q[st+lt+i-1] = rq[i];
div(l, mid, st, st+lt-1);
div(mid+1, r, st+lt, ed);
return ;
}
int main() {
//freopen(".in", "r", stdin);
//freopen(".out", "w", stdout);
n = gi(); m = gi();
for (int i = 1; i <= n; i++) {
q[++tot].op = 0, q[tot].x = i, X[++cnt] = q[tot].y = gi();
}
sort(X+1, X+1+cnt); cnt = unique(X+1, X+cnt+1)-X-1;//离散化
for (int i = 1; i <= n; i++)
q[i].y = lower_bound(X+1, X+cnt+1, q[i].y)-X;
for (int i = 1; i <= m; i++) {
q[++tot].op = i; q[tot].x = gi();q[tot].y = gi();q[tot].z = gi();
}
div(1, n, 1, tot);
for (int i = 1; i <= m; i++)
printf("%d\n", X[ans[i]]);
return 0;
}
静态区间第K小(整体二分、主席树)的更多相关文章
- 静态区间第k小 - 整体二分
蒟蒻终于学会整体二分啦! 思路 实现 丑陋无比的代码 #include <bits/stdc++.h> using namespace std; const int N = 200005; ...
- 【XSY2720】区间第k小 整体二分 可持久化线段树
题目描述 给你你个序列,每次求区间第\(k\)小的数. 本题中,如果一个数在询问区间中出现了超过\(w\)次,那么就把这个数视为\(n\). 强制在线. \(n\leq 100000,a_i<n ...
- POJ2104 K-th Number —— 区间第k小 整体二分
题目链接:https://vjudge.net/problem/POJ-2104 K-th Number Time Limit: 20000MS Memory Limit: 65536K Tota ...
- Dynamic Rankings || 动态/静态区间第k小(主席树)
JYF大佬说,一星期要写很多篇博客才会有人看 但是我做题没有那么快啊QwQ Part1 写在前面 区间第K小问题一直是主席树经典题=w=今天的重点是动态区间第K小问题.静态问题要求查询一个区间内的第k ...
- 51nod 1175 区间第k大 整体二分
题意: 一个长度为N的整数序列,编号0 - N - 1.进行Q次查询,查询编号i至j的所有数中,第K大的数是多少. 分析: 仅仅就是一道整体二分的入门题而已,没听说过整体二分? 其实就是一个分治的函数 ...
- [xdoj1216]子树第k小(dfs序+主席树)
解题关键:dfs序将树映射到区间,然后主席树求区间第k小,为模板题. #pragma comment(linker, "/STACK:1024000000,1024000000") ...
- 区间第K小——可持久化线段树模板
概念 可持久化线段树又叫主席树,之所以叫主席树是因为这东西是fotile主席创建出来的. 可持久化数据结构思想,就是保留整个操作的历史,即,对一个线段树进行操作之后,保留访问操作前的线段树的能力. 最 ...
- [luogu3834]静态区间第k小【主席树】
传送门:https://www.luogu.org/problemnew/show/P3834 题目描述 如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 分析 很多人都说是用 ...
- 主席树(可持久化线段树)静态区间第K小
传送门主席树 #include <bits/stdc++.h> #define int long long using namespace std; const int maxn=2e5+ ...
随机推荐
- JAVA中mark()和reset()用法
根据JAVA官方文档的描述,mark(int readlimit)方法表示,标记当前位置,并保证在mark以后最多可以读取readlimit字节数据,mark标记仍有效.如果在mark后读取超过rea ...
- 3.Dynamic Layout 动态布局。在槽中处理布局
在应用程序中,一个界面的布局基本都是固定的. 在这个实例中,我们把管理布局的代码放在槽中.这样点击一次按钮,触发槽.布局改变一次.这样就成为一个动态布局. (一) 水平和竖直布局改变 横向: 纵向: ...
- qt-vs-addin:Qt4和Qt5之VS插件如何共存与使用(转)
原则上,两者是不可以同时存在的,但是如果都安装了,该如何分别使用他们呢? Qt4 Visual Studio Add-in:官网可以下载安装程序,qt-vs-addin-1.1.11-opensour ...
- The Three Models of ASP.NET MVC Apps
12 June 2012 by Dino Esposito by Dino Esposito We've inherited from the original MVC pattern a ra ...
- css属性position的运用
随着web标准的规范化,网页的布局也随之千变万化.各种复杂漂亮有创意的页面布局冲 击这人们的视野,相比以前的table布局那就不是一等级的事儿.这个很大一部分功劳是css 样式的引入.而这个多样性布局 ...
- C++的惨痛教训(未完待续)
题记:只有痛才能让人铭记!痛促进进步~ 1. strncpy,大家都知道要做安全检查,可是谁都有嫌麻烦的时候,尤其是自己很自信不会产生溢出的时候,可能不会坑了自己,却会坑了使用这段代码的人.所以,1. ...
- 数组Byte [] 和 string 相互转换
using System; using System.Collections.Generic; using System.Text; namespace NET.MST.Fourth.StringBy ...
- Visual Assist X破解安装及设置
本文提供的插件版本为Visual Assist X 10.9.2248,支持Visual Studio 2010~2017各版本,本人亲测均可正常使用. 一. 插件下载: 点击下载链接,找到对应软件下 ...
- WPF 控件库——带有惯性的ScrollViewer
WPF 控件库系列博文地址: WPF 控件库——仿制Chrome的ColorPicker WPF 控件库——仿制Windows10的进度条 WPF 控件库——轮播控件 WPF 控件库——带有惯性的Sc ...
- 函数返回值string与返回值bool区别------c++程序设计原理与实践(进阶篇)
为什么find_from_addr()和find_subject()如此不同?比如,find_from_addr()返回bool值,而find_subject()返回string.原因在于我们想说明: ...