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. Google新出品的数据格式:Protocol Buffer

    转:http://blog.csdn.net/carson_ho/article/details/70037693

  2. 【题解】Radio stations Codeforces 762E CDQ分治

    虽然说好像这题有其他做法,但是在问题转化之后,使用CDQ分治是显而易见的 并且如果CDQ打的熟练的话,码量也不算大,打的也很快,思维难度也很小 没学过CDQ分治的话,可以去看看我的另一篇博客,是CDQ ...

  3. c# string 转 GUID

    提供两种方法 1.try...catch... /* * string TO guid */ private static bool ToGuid(string str) { Guid gv = ne ...

  4. 数据结构:Rope

    以BZOJ1507为例,这里仅仅展示动态区间问题的一些典型操作,包括插入删除和修改,查询的话不支持按顺序查询 使用起来很简单很方便 #include<cstdio> #include< ...

  5. LightOJ 1321 - Sending Packets 简单最短路+期望

    http://www.lightoj.com/volume_showproblem.php?problem=1321 题意:每条边都有概率无法经过,但可以重新尝试,现给出成功率,传输次数和传输时间,求 ...

  6. [洛谷P2597] [ZJOI2012]灾难

    洛谷题目链接:[ZJOI2012]灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引 ...

  7. bzoj 1052 dfs

    首先可以二分答案,将最优性问题转化为判定性问题. 对于二分到的边长,我们可以把所有的点看成一个大的矩形,这个矩形为包括所有点的最小矩形,那么贪心的想,3个正方形,第一个肯定放在这个矩形其中的一角,然后 ...

  8. hdu 1213 How Many Tables(并查集算法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1213 How Many Tables Time Limit: 2000/1000 MS (Java/O ...

  9. Django-【views】decorators.csrf

      views下导入方法 from django.views.decorators.csrf import csrf_exempt,csrf_protect csrf_exempt是全局需要,唯独这个 ...

  10. DSP学习教程基于28335(一)

    首先说明:开发环境Manjaro linux,内核5.0,滚动升级版本,随时都是最新,CCS也是最新的CCv 8 #include "DSP2833x_Device.h" // 这 ...