静态区间第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+ ...
随机推荐
- 用gdb+nm调试php c extension程序
.so写好了是给php脚本调用的,如果php脚本执行崩掉了,.so也只能在进程中饮恨而终,这时候php脚本调试经常用的echo, print_r, var_dump都派不上用场了.即使能打印一点儿错误 ...
- libevent源码深度剖析八
libevent源码深度剖析八 ——集成信号处理 张亮 现在我们已经了解了libevent的基本框架:事件管理框架和事件主循环.上节提到了libevent中I/O事件和Signal以及Timer事件的 ...
- Select2 的使用
实现这个下拉列表框 下载这两个官网上的CSS,JS 官网地址 https://select2.org/getting-started/installation 我自己存的高速下载地址 http://y ...
- c++策略模式(Strategy Method)
别人的博客再讲策略模式时都会讲三国,策略类就是赵云的锦囊,锦囊里装着若干妙计.在打仗时想要用什么妙计,直接从锦囊里去取. 锦囊类: class context { public: context(IS ...
- mybatis 框架 的应用之三(操作两张没有关联的表,存在主键和外键关系)
#注意:要配置开启多条语句操作,否则会报错( org.apache.ibatis.exceptions.PersistenceException) lf-driver=com.mysql.jdbc.D ...
- lucene和solr
我们为什么要用solr呢? 1.solr已经将整个索引操作功能封装好了的搜索引擎系统(企业级搜索引擎产品) 2.solr可以部署到单独的服务器上(WEB服务),它可以提供服务,我们的业务系统就只要发送 ...
- CF835F Roads in the Kingdom
话说这是去年大爷的一道NOIP模拟赛题,对着大爷的代码看了一堂课的我终于把这题写掉了. 本题要求在基环树给定的环上删去一条边使剩下的树的直径最小,输出这个最小直径. 那么基环树可以画成这样子的: 有一 ...
- 学习Vue.js需要了解的部分内容
重要: 1.如果要通过js/模板引用 图片到项目,图片路径需要使用require. 2.$event: $event 等于$emit 抛出的值,还可以使用$event.target.value. $e ...
- SpringMVC——处理 JSON:使用 HttpMessageConverter
一.SpringMVC处理JSON流程 1. 加入 jar 包: jackson-annotations-2.1.5.jarjackson-core-2.1.5.jarjackson-databind ...
- delphi让exe开机自启动
procedure AutoRunOnSystemStart(Title, FileName: String);const _Software_Microsoft_Windows_CurrentVe ...