题目链接

题解

主席树入门题

但是这里给出整体二分解法

整体二分顾名思义是把所有操作放在一起二分

想想,如果求\([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小(整体二分、主席树)的更多相关文章

  1. 静态区间第k小 - 整体二分

    蒟蒻终于学会整体二分啦! 思路 实现 丑陋无比的代码 #include <bits/stdc++.h> using namespace std; const int N = 200005; ...

  2. 【XSY2720】区间第k小 整体二分 可持久化线段树

    题目描述 给你你个序列,每次求区间第\(k\)小的数. 本题中,如果一个数在询问区间中出现了超过\(w\)次,那么就把这个数视为\(n\). 强制在线. \(n\leq 100000,a_i<n ...

  3. POJ2104 K-th Number —— 区间第k小 整体二分

    题目链接:https://vjudge.net/problem/POJ-2104 K-th Number Time Limit: 20000MS   Memory Limit: 65536K Tota ...

  4. Dynamic Rankings || 动态/静态区间第k小(主席树)

    JYF大佬说,一星期要写很多篇博客才会有人看 但是我做题没有那么快啊QwQ Part1 写在前面 区间第K小问题一直是主席树经典题=w=今天的重点是动态区间第K小问题.静态问题要求查询一个区间内的第k ...

  5. 51nod 1175 区间第k大 整体二分

    题意: 一个长度为N的整数序列,编号0 - N - 1.进行Q次查询,查询编号i至j的所有数中,第K大的数是多少. 分析: 仅仅就是一道整体二分的入门题而已,没听说过整体二分? 其实就是一个分治的函数 ...

  6. [xdoj1216]子树第k小(dfs序+主席树)

    解题关键:dfs序将树映射到区间,然后主席树求区间第k小,为模板题. #pragma comment(linker, "/STACK:1024000000,1024000000") ...

  7. 区间第K小——可持久化线段树模板

    概念 可持久化线段树又叫主席树,之所以叫主席树是因为这东西是fotile主席创建出来的. 可持久化数据结构思想,就是保留整个操作的历史,即,对一个线段树进行操作之后,保留访问操作前的线段树的能力. 最 ...

  8. [luogu3834]静态区间第k小【主席树】

    传送门:https://www.luogu.org/problemnew/show/P3834 题目描述 如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 分析 很多人都说是用 ...

  9. 主席树(可持久化线段树)静态区间第K小

    传送门主席树 #include <bits/stdc++.h> #define int long long using namespace std; const int maxn=2e5+ ...

随机推荐

  1. 【总结整理】AXURE原件

    iphone:750*1334 一般用分辨率的一半 移动的时候,按住shift拖动,可水平移动 框选的时候,箭头选择包含模式,只要不全部包含进来,就不会被选中 ctrl+'=显示背景网格 ctrl+s ...

  2. c语言实践 打印数字三角形

    效果如下图: 思路就是外层循环控制要打印的行数,里层循环控制每行打印的数字个数. int val = 65; for (int i = 0; i < 6; i++) { for (int j = ...

  3. Yii2邮箱发送与配置

    1配置邮箱 在 common/config/web.php中写入以下代码配置 Mail代理 return [ 'components' => [ ...//your code, //以下是 ma ...

  4. linux信号基本概念及如何产生信号

    linux信号基本概念及如何产生信号 摘自:https://blog.csdn.net/summy_j/article/details/73199069 2017年06月14日 09:34:21 阅读 ...

  5. ios7 设置status bar风格

    How to change status bar style during launch on iOS 7 up vote4down votefavorite   When I launch my a ...

  6. Linux基础-工作中经常使用到的linux 命令

     linux 常用命令 (1)命令ls——列出文件 ls -la 给出当前目录下所有文件的一个长列表,包括以句点开头的“隐藏”文件 ls a* 列出当前目录下以字母a开头的所有文件 ls -l *.d ...

  7. (转)菜鸟去重复之Sql

    原文地址:http://www.cnblogs.com/fatbird/p/Sql-Remove-duplicate.html 前言 本文主要是总结平时工作学习中遇到的使用Sql Server的去除重 ...

  8. .net IAsyncResult 异步操作

    //定义一个委托 public delegate int DoSomething(int count); //BeginInvoke 的回调函数 private static void Execute ...

  9. 【C#】 ref out

    ref 通常我们向方法中传递的是值,方法获得的是这些值的一个拷贝,然后使用这些拷贝,当方法运行完毕后,这些拷贝将被丢弃,而原来的值不会受到影响. 这种情况是通常的,当然还有另外一种情况,我们向方法传递 ...

  10. mysql升级到5.7时间戳报错

    往数据库里创建新表的时候报错: [Err] 1067 - Invalid default value for 'updateTime' DROP TABLE IF EXISTS `passwd_res ...