题目:给定一个长度为n的序列,进行加一减一的操作不超过k次,最多有多少个数相同?
思路:维护若干个区间,每个区间都能在k步内变为同一个数,求最长的区间。尽量往中位数靠。
两个问题:感觉有点像 O(n^2) ;而且偶数的时候,中位数默认是中间左边的数。
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
const int N = 1e5 + 10;
ll n, k, a[N], s[N];
bool judge(ll mid, int i, int j)
{
ll tmp = a[mid];
ll l = (mid-i) * tmp - (s[mid-1]-s[i-1]); // 从中位数到左端点 * 中位数与他们的差值 - 原本的数 = 左边需要操作的步数
ll r = s[j]-s[mid-1] - (j-mid+1) * tmp; // 右边也是同样的道理
if(l + r <= k ) return true;
return false;
}
int main()
{
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++) s[i] = s[i-1] + a[i];
int ans;
for(int i = 1, j = 1; i <= n; i++)
{
ll mid = (i+j+1) >> 1;
while(j <= n and judge(mid, i, j))
{
j++;
mid = (i+j+1) >> 1;
}
ans = max(ans, j-i);
}
cout << ans << endl;
return 0;
}

本文探讨了在给定序列中通过不超过k次加一减一操作,最大化相同数值的数量的算法。通过维护区间并寻找中位数附近的平衡,作者提供了一个O(n log n)复杂度的解决方案。讨论了可能存在的问题并给出C++代码实现。
591

被折叠的 条评论
为什么被折叠?



