K-th Number
Time Limit: 20000MS   Memory Limit: 65536K
Total Submissions: 45653   Accepted: 15177
Case Time Limit: 2000MS

Description

You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment.
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
first line of the input file contains n --- the size of the array, and m
--- the number of questions to answer (1 <= n <= 100 000, 1 <=
m <= 5 000).

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

For each question output the answer to it --- the k-th number in sorted a[i...j] segment.

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
转自:http://blog.csdn.net/famousdt/article/details/7064866 
建树的过程比较简单,对于区间[l,r],首先通过对原数组的排序找到这个区间的中位数a[mid],小于a[mid]的数划入它的左子树[l,mid-1],大于它的划入右子树[mid,r]。
同时,对于第i个数a[i],记录在[l,i]区间内有多少数被划入左子树。最后,对它的左子树区间[l,mid-1]和右子树区间[mid,r]递归的继续建树就可以了。
建树的时候要注意,对于被分到同一子树的元素,元素间的相对位置不能改变。

查找的过程中主要问题就是确定将要查找的区间。
  查找深度为dep,在大区间[L ,R]中找小区间[l ,r]中的第k元素。
 
我们的想法是,先判断[l ,r]中第k元素在[L ,R]的哪个子树中,然后找出对应的小区间和k,递归的进行查找,直到小区间的l==r为止。
 
通过之前的记录可以知道,在区间[L,l-1]中有(toleft[dep][l-1]-toleft[dep][L-1])进入左子树,
 
记它为x。


同理区间[L,r]中有(toleft[dep][r]-toleft[dep][L-1])个数进去左子树,记它为y。
 
所以,我们知道区间小区间[l,r]中有(y-x)个数进入左子树。那么如果(y-x)>=k,那么就在左子树中继续查找,否则就在右子树中继续查找。


接着,解决查找的小区间的问题。
  如果接下来要查找的是左子树,那么小区间应该是[L+([L,l-1]区间进入左子树的个数),L+([L,r]区间内进入左子树的个数)-1]。即区间[L+x,L+y-1]。(这里的-1应该是防止边界问题)
    显然,这里k不用变。
  如果接下来要查找的是右子树,那么小区间应该是[mid+([L,l-1]区间中进入右子树的个数),mid+([L,r]区间进入右子树的个数)-1]。
    即区间[mid+(l-L-x),mid+(r-L-y)]。(这里要记得+1)
    显然,这里k要减去区间里已经进入左子树的个数,即k变为k-(y-x)。

#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int MAXSIZE = ;
int tree[][MAXSIZE]; ///树最多也就30层
int _sort[MAXSIZE];
int toleft[][MAXSIZE]; void build(int l,int r,int deep)
{
if(l==r) return;
int mid =(l+r)>>;
int same = mid-l+; ///设这个变量的主要原因是判断tree[deep][i]==_sort[mid]时tree[deep][i]往哪边走
for(int i=l; i<=r; i++)///计算放于左子树中与中位数相等的数字个数,
{
// printf("%d ",tree[deep][i]);
if(tree[deep][i]<_sort[mid]) same--;
}
//printf("\n");
int left = l;
int right = mid+;
for(int i=l; i<=r; i++)
{
int flag = ;
if((tree[deep][i]<_sort[mid])||(tree[deep][i]==_sort[mid]&&same>))
{
flag = ;
tree[deep+][left++] = tree[deep][i];
if(tree[deep][i]==_sort[mid]) same--;
}
else
{
tree[deep+][right++] = tree[deep][i];
}
toleft[deep][i] = toleft[deep][i-]+flag;
}
build(l,mid,deep+);
build(mid+,r,deep+);
} int query(int L,int R,int l,int r,int k,int deep)
{
if(l==r) return tree[deep][l];
int x = toleft[deep][l-]-toleft[deep][L-]; ///x代表[L,l-1]区间内进入左子树的数字的量
int y = toleft[deep][r]- toleft[deep][L-]; ///y代表[L,r]区间内进入左子树的数字的量
int cnt = y-x; ///cnt代表[l,r]区间内进入左子树的数字的量
int mid = (L+R)>>;
int rx = l - L - x;///l左边放在右子树中的数字个数
int ry = r - L - y;///到r右边为止位于右子树的数字个数
if(cnt>=k)
{
query(L,mid,L+x,L+y-,k,deep+);
}else{
query(mid+,R,mid+rx+,mid+ry+,k-cnt,deep+);
} }
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{ memset(toleft,,sizeof(toleft));
for(int i=; i<=n; i++)
{
scanf("%d",&_sort[i]);
tree[][i] = _sort[i];
} sort(_sort+,_sort+n+);
build(,n,);
while(m--)
{
int a,b,k;
scanf("%d%d%d",&a,&b,&k);
int t = query(,n,a,b,k,);
printf("%d\n",t);
}
}
return ;
}
 

poj 2104(线段树)的更多相关文章

  1. K-th Number Poj - 2104 主席树

    K-th Number Poj - 2104 主席树 题意 给你n数字,然后有m次询问,询问一段区间内的第k小的数. 解题思路 这个题是限时训练做的题,我不会,看到这个题我开始是拒绝的,虽然题意清晰简 ...

  2. poj 2886 线段树+反素数

    Who Gets the Most Candies? Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 12744   Acc ...

  3. [poj 2104]主席树+静态区间第k大

    题目链接:http://poj.org/problem?id=2104 主席树入门题目,主席树其实就是可持久化权值线段树,rt[i]维护了前i个数中第i大(小)的数出现次数的信息,通过查询两棵树的差即 ...

  4. K-th Number POJ - 2104 划分树

    K-th Number You are working for Macrohard company in data structures department. After failing your ...

  5. poj 3468(线段树)

    http://poj.org/problem?id=3468 题意:给n个数字,从A1 …………An m次命令,Q是查询,查询a到b的区间和,c是更新,从a到b每个值都增加x.思路:这是一个很明显的线 ...

  6. POJ——3264线段树

    题目: 输入两个数(m,n),m表示牛的头数,n表示查询的个数.查询时输入两个数(x,y),表示查询范围的起始值和终止值,查询结果是,这个区间内牛重量的最大值减去牛重量的最小值,数量级为1000,00 ...

  7. POJ 2828 线段树(想法)

    Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 15422   Accepted: 7684 Desc ...

  8. poj 2828 线段树

    http://poj.org/problem?id=2828 学到的思维: 1.变化的或者后来的优先影响前面的,那么从最后一个往前看,最后一个就成了 确定的, 而且后来的也能够确定----假设从前往后 ...

  9. POJ - 1177 线段树

    POJ - 1177 扫描线 这道题也算是一道扫描线的经典题目了. 只不过这道题是算周长,非常有意思的一道题.我们已经知道了,一般求面积并,是如何求的,现在我们要把扫描线进行改造一下,使得能算周长. ...

  10. poj 2886 (线段树+反素数打表) Who Gets the Most Candies?

    http://poj.org/problem?id=2886 一群孩子从编号1到n按顺时针的方向围成一个圆,每个孩子手中卡片上有一个数字,首先是编号为k的孩子出去,如果他手上的数字m是正数,那么从他左 ...

随机推荐

  1. SpringMVC源码解析-DispatcherServlet启动流程和初始化

    在使用springmvc框架,会在web.xml文件配置一个DispatcherServlet,这正是web容器开始初始化,同时会在建立自己的上下文来持有SpringMVC的bean对象. 先从Dis ...

  2. 使用httpclient post请求中文乱码解决办法

    使用httpclient post请求中文乱码解决办法   在使用httpclient发送post请求的时候,接收端中文乱码问题解决. 正文: 我们都知道,一般情况下使用post请求是不会出现中文乱码 ...

  3. [codeforces/edu4]总结(F)

    链接:http://codeforces.com/contest/612/ A题: 枚举切多少个p,看剩下的能否整除q. B题: 从1到n模拟一下,累加移动的距离. C题: 先用括号匹配的思路看是否有 ...

  4. [mysql]数据库引擎查看

    1.查看数据库引擎 全局下,show engines; 2.察看数据库引擎 show variables like '%engine%'; 或者show create table xxx\G 会显示默 ...

  5. JQuery学习六

    <JQuery cookie>插件 cookie是保存在浏览器上的内容,用户在这次浏览页面的时候向cookie中保存文本内容.下次再访问页面的时侯就可以取出来上次保存的内容.这样可以得到上 ...

  6. getQueryString----获取url中得参数

    /** * 获取url中得参数 * @param name * @returns {null} */ window.getQueryString = function (name) { var reg ...

  7. python读书笔记-《简明python教程》上

    1月15日 <简明python教程>上 基本结构: 基础概念+控制流+函数+模块+数据结构+面向对象+I/O+异常+标准库+其他   1.概念 1-0    退出python linux: ...

  8. 第01篇 为什么推荐使用String直接赋值

    在四海学的时候,可能需要我们经过沉淀才会去想一些事情,有的时候不知道为什么这样或者那样的时候,从今天看是,胖先生打算给大家开辟一个课程,就是我的读书笔记. 首先我们来认识一下String字符串 一般对 ...

  9. vue实现菜单权限控制

    大家在做后台管理系统时一般都会涉及到菜单的权限控制问题.当然解决问题的方法无非两种——前端控制和后端控制.我们公司这边的产品迭代速度较快,所以我们是从前端控制路由迭代到后端控制路由.下面我会分别介绍这 ...

  10. LightOJ 1058 - Parallelogram Counting 几何思维

    http://www.lightoj.com/volume_showproblem.php?problem=1058 题意:给你顶点,问能够成多少个平行四边形. 思路:开始想使用长度来扫描有多少根,但 ...