又是不带修改的区间第k大,这次用的是一个不同的方法,划分树,划分树感觉上是模拟了快速排序的过程,依照pivot不断地往下划分,然后每一层多存一个toleft[i]数组,就可以知道在这一层里从0到i里有多少个被划分到了左子树,知道区间有多少个被分到左子树,就可以一路递归下去,不需要像函数式线段数一样,二分再加query,所以每次询问的复杂度也只是O(nlogn),空间复杂度的话就是O(nlogn),具体的介绍很多个链接都有,具体看下面给出的两个链接,它们对我起到非常大的帮助。

http://blog.csdn.net/famousdt/article/details/7064866

http://www.cnblogs.com/pony1993/archive/2012/07/17/2594544.html

写的时候尤其是递归询问区间的时候很容易出现off-by-one error,我在纸上比划了很久才搞清楚的。有点微弱呀- -0下面是代码。800多ms,是函数式线段数的时间的一半吧

#pragma warning(disable:4996)
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#define maxn 100000
using namespace std; int tree[22][maxn + 50];
int toleft[22][maxn + 50];
int as[maxn + 50];
int n, q; void build(int l, int r, int dep)
{
if (l == r) return;
int mid = (l + r) >> 1;
int same = mid - l + 1;
for (int i = l; i <= r; i++){
if (tree[dep][i] < as[mid]){
same--;
}
}
int ls = l;
int rs = mid + 1;
for (int i = l; i <= r; i++){
if (tree[dep][i] < as[mid]) tree[dep + 1][ls++] = tree[dep][i];
else if (tree[dep][i] == as[mid] && same) tree[dep + 1][ls++] = tree[dep][i], same--;
else tree[dep + 1][rs++] = tree[dep][i];
toleft[dep][i] = toleft[dep][l - 1] + ls - l;
}
build(l, mid, dep + 1);
build(mid + 1, r, dep + 1);
} int query(int left, int right, int k, int L, int R, int dep)
{
if (left == right) return tree[dep][left];
int mid = (L + R) >> 1;
int x = toleft[dep][left - 1] - toleft[dep][L - 1];
int y = toleft[dep][right] - toleft[dep][L - 1];
int rx = left - 1 - L + 1 - x;
int ry = right - L + 1 - y;
int cnt = y - x;
if (cnt >= k) return query(L + x, L + y - 1, k, L, mid, dep + 1);
// 注意off-by-one error.
else return query(mid + 1 + rx,mid + 1 + ry - 1, k - cnt, mid + 1, R, dep + 1);
} int main()
{
while (cin >> n >> q)
{
for (int i = 1; i <= n; i++){
scanf("%d", as + i);
tree[0][i] = as[i];
}
sort(as + 1, as + n + 1);
build(1, n, 0);
int li, ri, ki;
for (int i = 0; i < q; i++){
scanf("%d%d%d", &li, &ri, &ki);
printf("%d\n", query(li, ri, ki, 1, n, 0));
}
}
return 0;
}

POJ2104 k-th number 划分树的更多相关文章

  1. poj 2104 K-th Number 划分树,主席树讲解

    K-th Number Input The first line of the input file contains n --- the size of the array, and m --- t ...

  2. 静态区间第k大(划分树)

    POJ 2104为例[经典划分树问题] 思想: 利用快速排序思想, 建树时将区间内的值与区间中值相比,小于则放入左子树,大于则放入右子树,如果相等则放入左子树直到放满区间一半. 查询时,在建树过程中利 ...

  3. [NBUT 1458 Teemo]区间第k大问题,划分树

    裸的区间第k大问题,划分树搞起. #pragma comment(linker, "/STACK:10240000") #include <map> #include ...

  4. [hdu2665]Kth number(划分树求区间第k大)

    解题关键:划分树模板题. #include<cstdio> #include<cstring> #include<algorithm> #include<cs ...

  5. hdu 2665 Kth number(划分树模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=2665 [ poj 2104 2761 ]  改变一下输入就可以过 http://poj.org/problem? ...

  6. HDU 2665 Kth number(划分树)

    Kth number Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...

  7. HDU-2665-Kth number(划分树)

    Problem Description Give you a sequence and ask you the kth big number of a inteval.   Input The fir ...

  8. poj 2104 K-th Number (划分树入门 或者 主席树入门)

    题意:给n个数,m次询问,每次询问L到R中第k小的数是哪个 算法1:划分树 #include<cstdio> #include<cstring> #include<alg ...

  9. POJ 2104 K-th Number(划分树)

    题目链接 参考HH大神的模版.对其中一些转移,还没想清楚,大体明白上是怎么回事了,划分树就是类似快排,但有点点区别的.多做几个题,慢慢理解. #include <cstdio> #incl ...

随机推荐

  1. <postfix邮件服务下mysql的升级>

    本片服务的环境的红帽的企业版6.5 的,6.3的测试可能会略有不一样,不过方法大致是一样的. 当前系统的postfix的版本为 postfix-2.6.6-2.2.el6_1.x86_64 我们要向使 ...

  2. jQuery 遍历用法

    jQuery 遍历 DOM 树 parent() 方法返回被选元素的直接父元素(找爸爸). parents() 方法返回被选元素的所有祖先元素,它一路向上直到文档的根元素 (找长辈). parents ...

  3. linux服务器修改ssh默认22端口方法

    1.登录服务器,打开sshd_config文件 # vim /etc/ssh/sshd_config 2.找到#Port 22,默认是注释掉的,先把前面的#号去掉,再插入一行设置成你想要的端口号,注意 ...

  4. PHP CI 查询条件大全

    php CI 框架 this->db->where() 条件 PHP 5 版本 $this->db->where() 接受可选的第三个参数.如果你将它设置为 FALSE, Co ...

  5. C#中linq

    class IntroToLINQ { static void Main() { // The Three Parts of a LINQ Query: // 1. Data source. ] { ...

  6. FineUI 框架,RIA 富客户端应用的选择

    FineUI 框架演示地址:http://www.fineui.com/demo/ 是asp.net 和extjs 结合的框架,可以快速创建企业应用程序的界面,节省开发时间,具体使用详见fineUI ...

  7. [C/C++] 各种C/C++编译器对UTF-8源码文件的兼容性测试(VC、GCC、BCB)

    在不同平台上开发C/C++程序时,为了避免源码文件乱码,得采用UTF-8编码来存储源码文件.但是很多编译器对UTF-8源码文件兼容性不佳,于是我做了一些测试,分析了最佳保存方案. 一.测试程序 为了测 ...

  8. 关于字符串 “*****AB**C*D*****” 中前缀、后缀和中间 '*' 的处理

    一.删除前缀 '*' #include<iostream> #include<cstdio> using namespace std; //主函数 int main() { ] ...

  9. 简单的C#线程开发实例(隔一秒改变一下Label的Text)

    要实现的效果:点击按纽,窗口上的label上出现1~100数字的变化. 第一个实例(把窗口上的label上文字改成0): using System; using System.Windows.Form ...

  10. MySQL存储过程、函数和游标

    这里我新建了两个表,一个users和test CREATE TABLE users( username ), pwd ) ); CREATE TABLE test( id INT, username ...