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

POJ 2104 K-th Number ( 求取区间 K 大值 )

时间:2018-01-19 21:26:21      阅读:141      评论:0      收藏:0      [点我收藏+]

标签:复杂度   font   sort   开区   else   主席树   display   hid   family   

题意 : 给出一个含有 N 个数的序列,然后有 M 次问询,每次问询包含 ( L, R, K ) 要求你给出 L 到 R 这个区间的第 K 大是几

 

分析 :

求取区间 K 大值是个经典的问题,可以使用的方法有很多,我听过的只有主席树、整体二分法、划分树、分块……

因为是看《挑战》书介绍的平方分割方法(分块),所以先把分块说了,其他的坑以后再填

分块算法思想是将区间分为若干块,一般分为 n1/2 块然后在每块维护所需信息,可以把复杂度降到 O(根号n)

具体的分析和代码在《挑战程序设计竞赛》有很详细的解释,这里说一下代码的实现细节

题目在实现的时候用的是这种 [L, R) 左闭右开区间,这样的区间表示法在 STL 和 JAVA的类库中很常用

这样有很多优点,其中一个优点就是区间的长度是L ~ R,而判断两个区间的交或者并的时候思考的难度也降低很多。

L < R代表区间有值,L == R代表区间到了最后。用闭区间就特别麻烦,下面我给出的代码就是用闭区间的,纠结了我好久...

技术分享图片
#include<vector>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int B = 1000;
const int maxn = 1e5 + 10;
vector<int> bucket[maxn / B];
int num[maxn], arr[maxn];
int N, M;

int main(void)
{

    while(~scanf("%d %d", &N, &M)){
        for(int i=0; i<N; i++){
            scanf("%d", &arr[i]);
            bucket[i / B].push_back(arr[i]);
            num[i] = arr[i];
        }

        sort(num, num + N);
        for(int i=0; i<N/B; i++)
            sort(bucket[i].begin(), bucket[i].end());

        int L, R, K;
        while(M--){
            scanf("%d %d %d", &L, &R, &K);
            L--, R--;
            int lb = 0, ub = N - 1, ans = -1;
            while(ub >= lb){
                int mid = lb + ((ub - lb)>>1);
                int c = 0;
                int TL = L, TR = R;
                while(TR+1 > TL && TL % B != 0) if(arr[TL++] <= num[mid]) c++;
                while(TR+1 > TL && (TR+1) % B != 0) if(arr[TR--] <= num[mid]) c++;

                while(TR >= TL){
                    c += upper_bound(bucket[TL/B].begin(), bucket[TL/B].end(), num[mid]) - bucket[TL/B].begin();
                    TL += B;
                }

                if(c >= K) ans = mid, ub = mid - 1;
                else lb = mid + 1;
            }
            printf("%d\n", num[ans]);
        }
    }
    return 0;
}
View Code

 

POJ 2104 K-th Number ( 求取区间 K 大值 )

标签:复杂度   font   sort   开区   else   主席树   display   hid   family   

原文地址:https://www.cnblogs.com/Rubbishes/p/8318772.html

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