基准时间限制:1 秒 空间限制:131072 KB 分值: 40
难度:4级算法题
Input
第一行两个数n和k(1<=n<=100000,k<=n*(n-1)/2) 第二行n个数,0<=每个数<2^31
Output
一个数表示答案。
Input示例
4 2 1 2 3 2
Output示例
2
思路:
好像和ccpc哈尔滨一题很像。看了半天题解,才看懂。记下之前不明白的地方。
这个题是用二分和尺取来做的,但是之所以能用二分。应该是因为 ,满足了单调性(众数1> 众数2 >众数3),如果不满足这个关键性质就无法二分了。
之后是尺取,尺取的方法是找到我们二分出的众数x, 如果这个区间中的 y的个数(大于众数x) 就记录从n-r+1 这个区间长度(因为从当前l~ i(i>=r) y的个数必定都是大于x的, 也就没必要再枚举了)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <stdio.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int b[maxn], a[maxn], cnt[maxn];
int n,k;
bool work(int x)
{
int res=0;
memset(cnt,0,sizeof cnt);
int l=1;
for(int r=1; r<=n; r++)
{
cnt[a[r]]++;
while(cnt[a[r]]>=x&&l<r)
{
res+=n-r+1;
cnt[a[l]]--,l++;
}
if(res>=k) return true;
}
return false;
}
int main()
{
scanf("%d%d", &n, &k);
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);
for (int i = 1; i <= n; i++)
a[i] = lower_bound(b + 1, b + num + 1, a[i]) - (b + 1);
int l = 1, r = n;
int ans;
while (l <= r)
{
int mid = (l + r) / 2;
if (work(mid))
ans = mid, l = mid + 1;
else
r = mid - 1;
}
printf("%d\n", ans);
return 0;
}