51Nod - 1686 K-th largest interval (two points + feet)

The value that defines an interval is the number of times its mode occurs .
Now given n numbers, after sorting the values ​​of all intervals, what is the K-th largest value.


Mode (statistical/mathematical term) - Alchetron, The Free Social Encyclopedia 

Input two numbers n and k in the first line (1<=n<=100000, k<=n*(n-1)/2) 
n numbers in the second line, 0<=each number<2^31Output one The numbers indicate the answer. Sample Input
4 2
1 2 3 2
Sample Output
2

It must be noted that the value of an interval is the number of times the mode occurs. We can enumerate the answer, that is, what is the K-th largest value by bisection, and then verify the answer by taking the ruler. The idea is not difficult to say, but I don't think it is easy to think. This is the first time I have come into contact with the ruler method. Since the number is too large, after discretization, the num array can be implemented to record the number of times i appears in a certain interval.

Example: 1 2 3 1 2 2. If x is 1, then when num[1]=2, that is, the position of i moves to 4, then it conforms to the while loop. At this time, the interval 1 2 3 1, 1 2 3 1 2 , The values ​​of 1 2 3 1 2 2 are consistent, then endd+=ni. This is the meaning of a statement in the code, and then keep moving the left endpoint to see if it still meets the judgment conditions. If you move the left endpoint, num[l]--, that is, the value when l==1 is reduced by one, indicating that the interval is not Include this value, then l++.

#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
ll a[100005],b[100005],c[100005];
ll num[100005];//Record the number of times i appears in a certain interval
int n,k;
int aa(int x)
{
    memset(num,0,sizeof(num));
    ll l=0,endd=0;//l is the left endpoint, endd is the number whose interval value is greater than x
    for(int i=0; i<n; i++)
    {
        num[c[i]]++;
        while(num[c[i]]>x)//If x matches, then keep moving the left endpoint to the right to see if it matches
        {
            endd+=n-i;
            num[c[l]--;
            l++;
        }
    }
    if(endd>=k) return 0;
    return 1;
}
intmain()
{
    while(~scanf("%d%d",&n,&k))
    {
        for(int i=0; i<n; i++)
        {
            scanf("%lld",&a[i]);
            b[i]=a[i];
        }
        sort(b,b+n);//Prepare for deduplication
        int len=unique(b,b+n)-b;//Remove, prepare for discretization
        for(int i=0; i<n; i++)
        {
            c[i]=lower_bound(b,b+len,a[i])-b;//Discretization
        }
        int l=0,r=n,mid;//Two points to find the answer directly
        while(l<r)
        {
            mid=(l+r)/2;
            if(aa(mid))
                r=mid;
            else
                l=mid+1;
        }
        printf("%d\n",r);
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325943491&siteId=291194637