POJ 2104 K-th Number ( 求取区间 K 大值 || 主席树 || 离线线段树)
题意 : 给出一个含有 N 个数的序列,然后有 M 次问询,每次问询包含 ( L, R, K ) 要求你给出 L 到 R 这个区间的第 K 大是几
分析 :
求取区间 K 大值是个经典的问题,可以使用的方法有很多,我听过的只有主席树、整体二分法、划分树、分块……
因为是看《挑战》书介绍的平方分割方法(分块),所以先把分块说了,其他的坑以后再填
分块算法思想是将区间分为若干块,一般分为 n1/2 块然后在每块维护所需信息,可以把复杂度降到 O(根号n)
具体的分析和代码在《挑战程序设计竞赛》有很详细的解释,这里说一下代码的实现细节
题目在实现的时候用的是这种 [L, R) 左闭右开区间,这样的区间表示法在 STL 和 JAVA的类库中很常用
这样有很多优点,其中一个优点就是区间的长度是L ~ R,而判断两个区间的交或者并的时候思考的难度也降低很多。
L < R代表区间有值,L == R代表区间到了最后。用闭区间就特别麻烦,下面我给出的代码就是用闭区间的,纠结了我好久...
#include<vector>
#include<stdio.h>
#include<algorithm>
using namespace std;
;
;
vector<int> bucket[maxn / B];
int num[maxn], arr[maxn];
int N, M;
int main(void)
{
while(~scanf("%d %d", &N, &M)){
; i<N; i++){
scanf("%d", &arr[i]);
bucket[i / B].push_back(arr[i]);
num[i] = arr[i];
}
sort(num, num + N);
; i<N/B; i++)
sort(bucket[i].begin(), bucket[i].end());
int L, R, K;
while(M--){
scanf("%d %d %d", &L, &R, &K);
L--, R--;
, ub = N - , ans = -;
while(ub >= lb){
);
;
int TL = L, TR = R;
> TL && TL % B != ) if(arr[TL++] <= num[mid]) c++;
> TL && (TR+) % B != ) if(arr[TR--] <= num[mid]) c++;
while(TR >= TL){
c += upper_bound(bucket[TL/B].begin(), bucket[TL/B].end(), num[mid]) - bucket[TL/B].begin();
TL += B;
}
;
;
}
printf("%d\n", num[ans]);
}
}
;
}
2018-05-07 更新
省赛被 可持久化Trie 打爆,决定学习一下可持久化数据结构
学了主席树,离线求取 K 大值,注意一下离散化
#include<stdio.h>
#include<algorithm>
using namespace std;
;
];
int root[maxn], sz;
void Insert(int pre, int cur, int p, int l, int r)
{
if(l == r){
Node[cur].v = Node[pre].v + ;
return ;
}
);
if(p <= m){
Node[cur].lc = ++sz;
Node[cur].rc = Node[pre].rc;
Insert(Node[pre].lc, Node[cur].lc, p, l, m);
}else{
Node[cur].rc = ++sz;
Node[cur].lc = Node[pre].lc;
Insert(Node[pre].rc, Node[cur].rc, p, m+, r);
}
Node[cur].v = Node[Node[cur].lc].v + Node[Node[cur].rc].v;
}
int query(int L, int R, int l, int r, int k)
{
if(l == r) return l;
);
int tmp = Node[Node[R].lc].v - Node[Node[L].lc].v;
if(tmp >= k)
return query(Node[L].lc, Node[R].lc, l, m, k);
else
, r, k-tmp);
}
int arr[maxn];
int mp[maxn];
int main(void)
{
int N, M;
scanf("%d %d", &N, &M);
; i<N; i++)
scanf("%d", &arr[i]),
mp[i] = arr[i];
sort(mp, mp+N);
int len = unique(mp, mp+N) - mp;
; i<=N; i++){
]) - mp;
root[i] = ++sz;
Insert(root[i-], root[i], x+, , len);
}
int i, j, k;
while(M--){
scanf("%d %d %d", &i, &j, &k);
], root[j], , len, k);
printf(]);
}
;
}
POJ 2104 K-th Number ( 求取区间 K 大值 || 主席树 || 离线线段树)的更多相关文章
- [luoguP1440] 求m区间内的最小值(单调队列 || 线段树)
传送门 这种水题没必要搞线段树了,单调队列就行啊. ——代码 #include <cstdio> ; , t = ; int a[MAXN], q[MAXN]; int main() { ...
- 线性时间求取第 K 大数
求 Top K 的算法主要有基于快速排序的和基于堆的这两种,它们的时间复杂度都为 \(O(nlogK)\).借助于分治思想,以及快速排序的区间划分,我们可以做到 \(O(n)\) 时间复杂度.具体算法 ...
- poj 1523Tarjan算法的含义——求取割点可以分出的连通分量的个数
poj 1523Tarjan算法的含义——求取割点可以分出的连通分量的个数 题目大意:如题目所示 给你一些关系图——连通图,想要问你有没有个节点,损坏后,可以生成几个互相独立的网络(也就是连通分量), ...
- hdu6003 Problem Buyer 贪心 给定n个区间,以及m个数,求从n个区间中任意选k个区间,满足m个数都能在k个区间中找到一个包含它的区间,如果一个区间包含了x,那么 该区间不能再去包含另一个数,即k>=m。求最小的k。如果不存在这样的k,输出“IMPOSSIBLE!”。
/** 题目:hdu6003 Problem Buyer 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6003 题意:给定n个区间,以及m个数,求从n个区 ...
- 求余区间的求和类问题 离线+线段树 HDU4228
题目大意:给一个数组a,他的顺序是严格的单调增,然后有如下三个操作 ①加入一个val到a数组里面去,加入的位置就是a[i-1]<val<a[i+1] ②删除一个a[i]=val的值 ③查询 ...
- Splay(区间翻转)&树套树(Splay+线段树,90分)
study from: https://tiger0132.blog.luogu.org/slay-notes P3369 [模板]普通平衡树 #include <cstdio> #inc ...
- HDU 5700 区间交 离线线段树
区间交 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5700 Description 小A有一个含有n个非负整数的数列与m个区间.每个区间可以表示为 ...
- [BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树)
[BZOJ 3110] [luogu 3332] [ZJOI 2013]k大数查询(权值线段树套线段树) 题面 原题面有点歧义,不过从样例可以看出来真正的意思 有n个位置,每个位置可以看做一个集合. ...
- bzoj 3110 [Zjoi2013]K大数查询——线段树套线段树(标记永久化)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3110 第一道线段树套线段树! 第一道标记永久化! 为什么为什么写了两个半小时啊…… 本想线段 ...
随机推荐
- 【Qt开发】如何将内存图像数据封装成QImage V1
如何将内存图像数据封装成QImage 当采用Qt开发相机数据采集软件时,势必会遇到采集内存图像并进行处理(如缩放.旋转)操作.如果能够将内存图像数据封装成QImage,则可以利用QImage强大的图像 ...
- CentOS7.查看进程占用端口情况
1.命令:"netstat -lntp" 2.没有改命令的话,需要安装 net-tools工具:"yum install net-tools" 3. 4. 5.
- linux/linux学习笔记-vim文本编辑器(mooc)
vim文本编辑器 vim与vi的区别:( vim=vi +IMproved) VIM是一个Unix以及类unix文本编辑器 特点:功能强大,高度可定制 vim编辑器的三种模式:一般模式.编辑模式和命令 ...
- <<用法
数据移位运算符,左移几位,如:x=i<<4;就是将i的值左移4位(放大2的4次方)后,赋给x,若i=2,则X=32.
- IDEA 快捷键 (长期更新)
自动清除无效 import 和 清除无效 import ctrl+alt+o
- 极*Java速成教程 - (8)
Java高级特性 注解 注解可以在代码之外添加更多的信息,更加完整地描述程序,帮助编译器进行工作,或者实现某些特定的Java代码之外的功能. 注解可以简化某些重复的流程,自动化那些过程. 注解的使用 ...
- Windows上Tomcat安装以及解决乱码问题
Windows上Tomcat安装以及解决乱码问题 下载tomcat8 1.进入tomcat官网 官方网站 2.选择windows的版本 解压 确定自己配置好了jdk jdk的相关配置 配置好tomca ...
- 剑指offer-动态规划-贪心算法--剪绳子-python
题目描述 给你一根长度为n的绳子,请把绳子剪成m段(m.n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m].请问k[0]xk[1]x...xk[m]可能 ...
- elementUI 等 UI框架中,@change方法传递参数
有些业务中,在使用 @change 回调的时候需要动态获取当前循环下的特定值,但是@change方法一旦传递参数就会覆盖原本的数据,对此,有两种方法解决: // 这种方法据说会改变 this 指向 ...
- lldb调试命令
XCode4.0以后,编译器换成了LLVM 编译器 2.0 与以前相比,更加强大:1.LLVM 编译器是下一带开源的编译技术.完全支持C, Objective-C, 和 C++.2.LLVM 速度比 ...