划分树 poj2104 hdu5249
KPI
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 616 Accepted Submission(s): 261
每组数据第一行有一个n(1≤n≤10000),代表服务记录数。
接下来有n行。每一行有3种形式
"in x": 代表重要值为x(0≤x≤109)的请求被推进管道。
"out": 代表服务拉取了管道头部的请求。
"query: 代表我想知道当前管道内请求重要值的中间值. 那就是说,假设当前管道内有m条请求, 我想知道。升序排序后第floor(m/2)+1th
条请求的重要值.
为了让题目简单,全部的x都不同。而且假设管道内没有值。就不会有"out"和"query"操作。
Case #i:
然后每一次"query"。输出当前管道内重要值的中间值。
6
in 874
query
out
in 24622
in 12194
query
Case #1:
874
24622
Time Limit: 20000MS | Memory Limit: 65536K | |
Total Submissions: 41138 | Accepted: 13447 | |
Case Time Limit: 2000MS |
Description
That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?
"
For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.
Input
The second line contains n different integer numbers not exceeding 109 by their absolute values --- the array for which the answers should be given.
The following m lines contain question descriptions, each description consists of three numbers: i, j, and k (1 <= i <= j <= n, 1 <= k <= j - i + 1) and represents the question Q(i, j, k).
Output
Sample Input
7 3
1 5 2 6 3 7 4
2 5 3
4 4 1
1 7 3
Sample Output
5
6
3
Hint
This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.
这两题都 要求子区间的第k大数,假设用快排之后,再查,复杂度太大。不能过,就要用到划分树了,划分树。事实上,就是线段树的
一个变种了,当然,这样做查询是lg(n)级别,建树是n * lg(n),再加上一次快排,也是n * lg(n),差点儿相同就能够过了!
先来看看划分树,我们在线段树的基础上,假设每一个结点都保存了。当前子段向左子树走的个数。假设,查询的k要小于,查询段向左走的个数,自然,我们向左子树就能够查到结果。假设,k>向左走的个数,当然要向右找k-midcount个数,区间的变换。我们能够
推一下向左走就是l + scount, l + ecount - 1。向右走就是mid + 1 + s - l - scount, mid + 1 + e - l - ecount,当中scount就是s之前向左走的个数。 ecount,就是e之前向左走的个数。
上核心代码
#define MID(a,b) (((a)+(b))>>1)
#define N 100050
int num[20][N], val[20][N];
//第i层,向左包含自已,向左子树的个数,当前的值
int pri[N], sorted[N];
//原始和排序后的数列
char str[20];
void build(int l, int r, int layer){
if (l >= r){
return;
}
int mid = MID(l, r);
int ql = l, qr = mid + 1, leftCount = mid, eqCount = 0;
for (int i = l; i <= r; i++)
leftCount -= val[layer][i] < sorted[mid];
for (int i = l; i <= r; i++){
if (i == l){
num[layer][i] = 0;
}
else{
num[layer][i] = num[layer][i - 1];
}
if (val[layer][i] < sorted[mid]){
num[layer][i]++;
val[layer + 1][ql++] = val[layer][i];
}
else if (val[layer][i] > sorted[mid]){
val[layer + 1][qr++] = val[layer][i];
}
else {
if (eqCount < leftCount){
eqCount++;
num[layer][i]++;
val[layer + 1][ql++] = val[layer][i];
}
else {
val[layer + 1][qr++] = val[layer][i];
}
}
}
build(l, mid, layer + 1);
build(mid + 1, r, layer + 1);
}
//在layer层l到r间,找s-e之间的第k大数
int query(int l, int r, int layer, int s, int e, int k){
if (l >= r || s >= e){
return val[layer][s];
}
int scount, ecount, mid = MID(l, r);
if (s == l){
scount = 0, ecount = num[layer][e];
}
else {
scount = num[layer][s - 1], ecount = num[layer][e];
}
int midcount = ecount - scount;
if (k <= midcount){
return query(l, mid, layer + 1, l + scount, l + ecount - 1, k);
}
else {
return query(mid + 1, r, layer + 1, mid + 1 + s - l - scount, mid + 1 + e - l - ecount, k - midcount);
}
}
int main()
{
int tcase, tcasenum = 0;
int n, k, q, s, e, begin = 1, nn, qcount, m;
while (S2(n, m) != EOF)
{
FI(n){
S(val[0][i+1]);
}
FI(n){
sorted[i + 1] = val[0][i + 1];
}
sort(sorted + 1, sorted + n + 1);
build(1, n, 0);
FI(m){
S2(s, e); S(q);
Prn(query(1, n, 0, s,e,q));
}
}
return 0;
}
划分树 poj2104 hdu5249的更多相关文章
- poj2104(划分树模板)
poj2104 题意 给出一个序列,每次查询一个区间,要求告诉这个区间排序后的第k个数. 分析 划分树模板,O(mlogn). 建树.根据排序之后的数组,对于一个区间,找到中点的数,将整个区间分为左右 ...
- 划分树(poj2104)
poj2104 题意:给出n个数,有m次查询,每次查询要你找出 l 到 r 中第 k 大的数: 思路:划分树模板题 上述图片展现了查询时如何往下递推的过程 其中ly表示 [sl,l) 中有多少个数进入 ...
- poj2104(划分树模板)
poj2104 题意 给出一个序列,每次查询一个区间,要求告诉这个区间排序后的第k个数. 分析 划分树模板,O(mlogn). 建树.根据排序之后的数组,对于一个区间,找到中点的数,将整个区间分为左右 ...
- poj2104&&poj2761 (主席树&&划分树)主席树静态区间第k大模板
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 43315 Accepted: 14296 Ca ...
- 初学划分树,小见解之!POJ-2104/HDU-2665
划分树 本来是学主席树的,可怜我等巨弱观群巨博客难解fotle主席的思想精髓.于是学了一下划分树,嗯,花了一下午时间理解build(其实自己模拟一遍就通了),我很难理解为什么划分树会看不懂而能学会主席 ...
- hdu2665 && poj2104划分树
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 47066 Accepted: 15743 Ca ...
- poj2104 线段树 划分树
学习:http://www.cnblogs.com/pony1993/archive/2012/07/17/2594544.html 划分树的build: 划分树是分层构建的,在构建的t层时,我们可以 ...
- POJ2104 k-th number 划分树
又是不带修改的区间第k大,这次用的是一个不同的方法,划分树,划分树感觉上是模拟了快速排序的过程,依照pivot不断地往下划分,然后每一层多存一个toleft[i]数组,就可以知道在这一层里从0到i里有 ...
- poj2104 划分树 区间K大 在线 无修改
博主sbit....对于高级数据结构深感无力,然后这些东西在OI竟然烂大街了,不搞就整个人都不好了呢. 于是我勇猛的跳进了这个大坑 ——sbit 区间K大的裸题,在线,无修改. 可以用归并树(\(O( ...
随机推荐
- JavaScript 中的事件设计
1. 事件绑定的几种方式 主要介绍一下 最常用的事件设计 其他就稍微带过. 直接在代码里面添加onclick指定函数名字. B) 在JS代码中通过dom元素的onclick等属性 这种做法this表 ...
- 关于sys、system、sysman等在EM中登录的问题
1.sysman要先在SQL*Plus上解锁: (1)以"sysdba"的身份登录 conn system/密码 as sysdba; (2)解锁 alter user sysma ...
- 《第一行代码》学习笔记15-UI(4)
1.ListView允许用户通过手指上下滑动的方式将屏幕外的数据滚动到屏幕内,同时屏幕上原有的数据则会滚动出屏幕. 2.数组中的数据无法直接传递给ListView,得借助适配器来完成.此处使用Arra ...
- 客户Oracle数据库在插入数据的时候报超出最大长度的错误(规避风险)
背景: 项目使用oracle数据,在开发环境测试一些正常.项目部署到客户的服务器上后,系统在添加数据的时候报错.输出错误信息,发现是“超出最大长度”的异常. 但是按照数据库的设计,添加的数据应该在允许 ...
- Memcached的一些知识
一.内存分配在Memcached内存结构中有两个非常重要的概念:slab 和 chunk,我们先从下图中对这两个概念有一个感性的认识: memcached内存结构Slab是一个内存块,它是memcac ...
- C# 参数按照ASCII码从小到大排序(字典序)
在对接第三方支付的时候,第三方会要求参数按照ASCII码从小到大排序.如下: public static void requestPay() { Dictionary<string, strin ...
- python学习第二天 --变量及其字符串
python变量: 在计算机程序中,变量不仅可以是数字,还可以是任意数据类型. 在Python程序中,变量是用一个变量名表示,变量名必须是大小写英文.数字和下划线(_)的组合,且不能用数字开头. 在P ...
- 字符串:各种奇葩的内置方法 - 零基础入门学习Python014
字符串:各种奇葩的内置方法 让编程改变世界 Change the world by program 字符串:各种奇葩的内置方法 或许现在又回过头来谈字符串,有些朋友可能会觉得没必要,也有些朋友会觉得不 ...
- C语言多维数组的地址
设有整型二维数组a[3][4]如下: 0 1 2 3 4 5 6 7 8 9 10 11 它的定义为: int a[3][4]={{0,1,2,3},{4,5 ...
- hadoop学习之hadoop完全分布式集群安装
注:本文的主要目的是为了记录自己的学习过程,也方便与大家做交流.转载请注明来自: http://blog.csdn.net/ab198604/article/details/8250461 要想深入的 ...