1. 程式人生 > >hdu 6231 -- K-th Number(二分+尺取)

hdu 6231 -- K-th Number(二分+尺取)

lld name scrip string php doesn title frame review

題目鏈接

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

題意:有個數列包含n個數,現在從這個數列中取出所有子區間中的第k大的數(所有長度大於等於k的子區間),構成一個新的數列,求這個新的數列的第M大的數?

思路:我們可以利用尺取求出區間第k大數大於等於x的這樣的區間有多少個,然後根據這個進行二分求出準確的第M大數,時間復雜度O(n*log n)。

代碼如下:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int N=1e5+5;
int a[N],b[N];

LL get(int x,int n,int k)
{
    LL ans=0;
    int pos=1;
    int num=0;
    for(int i=1;i<=n;i++)
    {
        if(a[i]>=x) num++;
        if(num==k)
        {
            ans+=n-i+1;
            while(a[pos]<x)
            {
                ans+=n-i+1;
                pos++;
            }
            num--; pos++;
        }
    }
    return ans;
}

int main()
{
    int T; cin>>T;
    while(T--)
    {
        int n,k;
        LL m;
        scanf("%d%d%lld",&n,&k,&m);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]), b[i]=a[i];
        sort(b+1,b+n+1);
        int num=unique(b+1,b+n+1)-(b+1);
        int L=1,R=num;
        while(L<=R)
        {
            int mid=(L+R)>>1;
            LL tmp=get(b[mid],n,k);
            if(tmp<m) R=mid-1;
            else L=mid+1;
        }
        printf("%d\n",b[L-1]);
    }
    return 0;
}

hdu 6231 -- K-th Number(二分+尺取)