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

K-th Number



Problem Description
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(1N105),K(1KN),M. The second line contains  N numbers  Ai(1Ai109).

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,对于A的每一个区间,求第K大,插入到数列B中,最后再求数列B的第M大!


解题思路:二分答案+尺取法判断。看了题解才会,真的很巧妙,这都能二分。对于当前答案,如果当前答案作为第K大的区间的总数大于M,那么证明实际答案要比当前答案大,反之则小。如果这个能懂的话,就知道怎么二分了。难点变为怎么统计答案作为第K大的区间个数,这里用到了尺取法。尺取法很容易理解,跟着代码跑一边就懂了。




#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long int ll;

int N,K;
ll M;
int a[100005];

bool judge(int x){
    ll ans=0;//区间个数
    int num=0;//当前>x的数的个数
    int j=1;

    for(int i=1;i<=N;i++){
        if(a[i]>=x)
            num++;
        if(num==K){
            ans+=N-i+1;//统计后面一共可以形成多少个区间
            while(a[j]=M)
        return true;
    else
        return false;
    
}


int main(){
    int t;
    scanf("%d",&t);

    while(t--){
        scanf("%d%d%lld",&N,&K,&M);

        for(int i=1;i<=N;i++)
            scanf("%d",&a[i]);

        int l=1,r=1000000000;
        int m;
        while(l




你可能感兴趣的:(————ACM相关————,——搜索相关——,ACM,-,二分三分搜索,——算法技巧——,ACM,-,尺取法)