51nod 1686 第K大区间(二分+尺取)

问你在所有区间中,排第k的那个区间是多少(根据众数值排列)
这题看了题解,一开始想要使用类似递推的方法..毫无用处

发现是要利用好众数存在单调性,就可以尺取了..

做一下离散化,时间卡的难受

#include <iostream>
#include <vector>
#include <set>
#include <map>
using namespace std;
#define debug(x) //std::cerr << #x << " = " << (x) << std::endl
typedef long long LL;
const int MAXN = 1e5 + 17;
const int MOD = 1e9 + 7;
LL a[MAXN],n,k;
bool check(LL x)
{
    vector<int > mp(MAXN,0);
    LL ed = n+2,sum = 0;
    for (int i = 0; i < n; ++i)
    {
        int tmp = mp[a[i]];
        mp[a[i]]++,tmp++;
        if(tmp==x)
        {
            ed = i+1;
            break;
        }
    }
    sum += n-ed+1;
    for (int i = 0; i < n; ++i)
    {
        int tmp = mp[a[i]];
        mp[a[i]]--;
        if(tmp!=x)
        {
            sum += n-ed+1;
            continue;
        }
        while(ed<n)
        {
            tmp = mp[a[ed]];
            mp[a[ed]]++,tmp++;
            ed++;
            if(tmp==x) break;
        }
        if(tmp==x)
        {
            sum += n-ed+1;
            continue;
        }
        else
        {
            break;
        }
    }
    if(sum>=k)
        return true;
    else
        return false;
}
int main(int argc, char const *argv[])
{
#ifdef noob
    freopen("Input.txt", "r", stdin);
    freopen("Output.txt", "w", stdout);
#endif
    cin>>n>>k;
    set<int > s;
    for(int i = 0; i < n; i++)
    {
        scanf("%lld",&a[i]);
        s.insert(a[i]);
    }
    int tmp = 1;
    map<LL,int > mp;
    for(auto i : s)
    {
        mp[i] = tmp;
        tmp++;
    }
    for (int i = 0; i < n; ++i)
    {
        a[i] = mp[a[i]];
    }
    LL l = 0,r = n*(n-1)/2+1;
    while(r-l>1)
    {
        LL mid = (r+l)/2;
        if(check(mid))
            l = mid;
        else
            r = mid;
    }
    cout<<l<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37802215/article/details/81073476