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

HDU - 6231 K-th Number (2017CCPC哈尔滨站 二分+尺取法)

时间:2017-11-19 19:40:52      阅读:219      评论:0      收藏:0      [点我收藏+]

标签:while   for   cout   positive   +=   can   pos   build   之间   

Alice are given an array A[1..N] with N numbers.

Now Alice want to build an array B by a parameter K as following rules:

Initially, the array B is empty. Consider each interval in array A. If the length of this interval is less than K, then ignore this interval. Otherwise, find the K-th largest number in this interval and add this number into array B.

In fact Alice doesn‘t care each element in the array B. She only wants to know the M-th largest element in the array B
    . Please help her to find this number.
Input
    The first line is the number of test cases.

    For each test case, the first line contains three positive numbers N(1≤N≤105),K(1≤K≤N),M. The second line contains N numbers Ai(1≤Ai≤109)
    .

    It‘s guaranteed that M is not greater than the length of the array B.
Output
    For each test case, output a single line containing the M-th largest element in the array B
    .
Sample Input

    2
    5 3 2
    2 3 1 5 4
    3 3 1
    5 8 2

Sample Output

    3
    2

 

题意:给你个数组A,将每个区间的第k大的数字加入数组B,不存在则跳过,求B中第m大的数

题解:二分答案,尺取法计当大于mid的第k大个数的个数,如果大于m,则说明答案在mid与right之间,否则在left与mid之间。(二分左闭右开)

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
#define maxn 100010
#define CLR(a,b) memset(a,b,sizeof(a))
long long n,k,m;
int a[maxn];

bool check(int mid)
{
    int cnt = 0;
    int l = 1;
    int r = 0;
    long long sum = 0;
    while(r<=n){
        if(cnt < k){
            r++;
            if(a[r] >= mid) cnt++;
        }
        if(cnt >= k){
            sum+=(n-r+1);
            if(a[l] >= mid) cnt--;
            l++;
        }
    }
    return (sum>=m);
}

int main()
{
    int t;
    cin>>t;
    while(t--){
        cin>>n>>k>>m;
        int l = 1;
        int r = 0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            r = max(a[i]+1,r);
        }
        while(l+1<r){
            int mid = (r+l)/2;
            if(check(mid))
                l = mid;
            else
                r = mid;
        }
        cout<<l<<endl;
    }
    return 0;
}

/*

1
8 3 4
2 3 1 5 3 4 4 5

*/

 

HDU - 6231 K-th Number (2017CCPC哈尔滨站 二分+尺取法)

标签:while   for   cout   positive   +=   can   pos   build   之间   

原文地址:http://www.cnblogs.com/Tokisaki-Kurumi-/p/7860652.html

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