题目大意
小Z组织训练营同学进行一次拔河比赛, 要从n(2<=n<=60,000)个同学中选出两组同学参加(两组人数可能不同) .对每组同学而言,如果人数超过1人,那么要求该组内的任意两个同学的体重之差的绝对值不超过k (包含k)。问最多有几个同学能参加比赛?
输入描述:
第一行为两个整数n和k (0<=k<=1e9)
接下来是n行,每行一个正整数,表示每个同学的体重,保证均为正整数且不超过1e9。
解题思路
先排序。然后枚举起点,二分出最大终点。
对于每个位置iii,得到三个属性R[i]R[i]R[i],最大终点。len[i]:R[i]−i+1len[i]:R[i]-i+1len[i]:R[i]−i+1,也就是最大长度。suffix[i]suffix[i]suffix[i]:后缀最大lenlenlen。
然后再枚举每个位置,ans=max(ans,len[i]+,suffux[R[i]+1])ans=max(ans, len[i]+,suffux[R[i]+1])ans=max(ans,len[i]+,suffux[R[i]+1])。
时间复杂度O(nlogn)O(nlogn)O(nlogn)。
#include <bits/stdc++.h>
using namespace std;
int a[60010];
int R[60010];
int len[60010];
int suffix[60010];
int main()
{
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++)
cin >> a[i];
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i++)
{
int l = i + 1, r = n, ans = i;
while (l <= r)
{
int mid = l + r >> 1;
if (a[mid] <= a[i] + k)
{
ans = mid;
l = mid + 1;
}
else
r = mid - 1;
}
R[i] = ans;
len[i] = R[i] - i + 1;
}
if (R[1] == n)
return cout << n << endl, 0;
for (int i = n; i >= 1; i--)
suffix[i] = max(suffix[i + 1], len[i]);
int ans = 0;
for (int i = 1; i <= n; i++)
{
if (R[i] + 1 > n)
continue;
int res1 = len[i];
int res2 = suffix[R[i] + 1];
ans = max(res1 + res2, ans);
}
cout << ans << endl;
return 0;
}