码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 2665 Kth number (poj 2104 K-th Number) 划分树

时间:2015-04-20 10:47:14      阅读:141      评论:0      收藏:0      [点我收藏+]

标签:

划分树的基本功能是,对一个给定的数组,求区间[l,r]内的第k大(小)数。

划分树的基本思想是分治,每次查询复杂度为O(log(n)),n是数组规模。

具体原理见http://baike.baidu.com/link?url=vIUKtsKYx7byeS2KCOHUI14bt_0sdHAa9BA1VceHdGsTv5jVq36SfZgBKdaHYUGqIGvIGrE_aJtqy0D0b1fCoq

个人感觉看代码是最好的学习方法。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 100100

int a[N];
int s[30][N];//划分树
int num[30][N];//num[i][j] - num[i][j-1] == 1表示第i层第j个数在下层中要被划入左子树

void build(int l, int r, int dep = 1)
{
    if(l == r){
        s[dep][l] = s[dep-1][l];
        return;
    }
    int mid = l+r>>1;
    int cnt = mid-l+1;
    for(int i = l; i <= r; i++) if(s[dep-1][i] < a[mid]) cnt--;
    int c1 = l, c2 = mid+1;
    for(int i = l; i <= r; i++)
    {
        if(s[dep-1][i] < a[mid] || ( s[dep-1][i] == a[mid] && cnt-- > 0)) s[dep][c1++] = s[dep-1][i];
        else s[dep][c2++] = s[dep-1][i];

        num[dep-1][i] = num[dep-1][l-1]+c1-l;
    }
    build(l, mid, dep+1);
    build(mid+1, r, dep+1);
}

int query(int l, int r, int k, int L, int R, int dep = 0)
{
    if(l == r) return s[dep][l];
    int mid = L+R>>1;
    int cnt = num[dep][r] - num[dep][l-1];

    if(cnt >= k)
    {
        int nl = L+num[dep][l-1]-num[dep][L-1];
        int nr = nl+cnt-1;
        return query(nl, nr, k, L, mid, dep+1);
    }
    else
    {
        int nr = r+num[dep][R]-num[dep][r];
        int nl = nr - (r-l-cnt);
        return query(nl, nr, k-cnt, mid+1, R, dep+1);
    }
}

int main()
{
    int T, n, m;
    scanf("%d", &T);
    while(T--)
    //while(~scanf("%d %d", &n, &m)) 
    {
        memset(num, 0, sizeof(num));
        scanf("%d %d", &n, &m);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
        for(int i = 1; i <= n; i++) s[0][i] = a[i];
        sort(a+1, a+n+1);
        build(1, n);
        for(int i = 0; i < m; i++)
        {
            int l, r, k;
            scanf("%d %d %d", &l, &r, &k);
            printf("%d\n", query(l, r, k, 1, n));
        }

    }
    return 0;
}

 

hdu 2665 Kth number (poj 2104 K-th Number) 划分树

标签:

原文地址:http://www.cnblogs.com/beisong/p/4440700.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!