poj 2104 K-th Number 划分树

poj 2104 K-th Number
//poj 2104 K-th Number

//划分树



//建树和查找,模板题,具体看代码



#define infile freopen("in.txt", "r", stdin);

#include <stdio.h>

#include <string.h>

#include <algorithm>

using namespace std;



#define N 100005



int ans;

int level[20][N], sorted[N], l_cnt[20][N];



void build(int l, int r, int loc, int dep)

{

    if(l == r)

        return;

    int mid = l + (r-l)/2;

    int mid_val = sorted[mid];



    int cnt = 0;    //记录小于mid_val的个数

    for(int i = l; i <= r; ++i)

        if(level[dep][i] < mid_val)

            cnt++;

    //这里l_tot是从l开始···equal_cnt记录跟mid_val相等且进入左子树的个数

    int l_tot = l, r_tot = mid+1, equal_cnt = 0;

    for(int i = l; i <= r; ++i)

    {

        if(level[dep][i] < mid_val) //小于mid_val的进入左子树

            level[dep+1][l_tot++] = level[dep][i];

        else if(level[dep][i] == mid_val && mid-l+1-cnt > equal_cnt)

        {   //等于mid_val的且没超过左子树限定个数的时候进入左子树

            equal_cnt++;

            level[dep+1][l_tot++] = level[dep][i];

        }

        else

            level[dep+1][r_tot++] = level[dep][i];

        l_cnt[dep][i] = l_tot - l;//记录进入左子树的个数

    }

    build(l, mid, loc*2, dep+1);

    build(mid+1, r, loc*2+1, dep+1);

}



void find(int l, int r, int from, int to, int k, int dep)

{

    if(l == r)

    {

        ans = level[dep][l];

        return;

    }

    int mid = l + (r-l)/2;

    int from_cnt;   //记录当前层中,from以前的数进入左子树的个数

    if(from > 1)    //不包括from

        from_cnt = l_cnt[dep][l+from - 2];

    else

        from_cnt = 0;

    //记录当前层中,to以前的数进入又子树的个数,包括to

    int to_cnt = l_cnt[dep][l+to - 1];





    //接下去那层就应该保持和这层一样的起点,即from左边的个数不变

    //若下一层到左子树,则要从from以左的进入左子树的个数(from_cnt)开始

    //由于from这个数也到左子树所以下一层应从from_cnt+1开始

    //若下一层到右子树要去掉进入左子树的个数

    if(to_cnt - from_cnt >= k)  //from到to之间进入左子树的个数

        find(l, mid, from_cnt+1, to_cnt, k, dep+1);

    else

        find(mid+1, r, from-from_cnt, to-to_cnt, k-(to_cnt-from_cnt), dep+1);

}



int main(void)

{

    //infile

    int n, n_query;

    while(scanf("%d%d", &n, &n_query) != EOF)

    {

        for(int i = 1; i <= n; ++i)

        {

            scanf("%d", &level[1][i]);

            sorted[i] = level[1][i];

        }

        sort(sorted+1, sorted+n+1);

        build(1, n, 1, 1);

        while(n_query--)

        {

            int from, to, k;

            scanf("%d%d%d", &from, &to, &k);

            find(1, n, from, to, k, 1);

            printf("%d\n", ans);

        }

    }

    return 0;

}

还不懂的话可以看看这个

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

你可能感兴趣的:(number)