B题
思路:二分 + 前缀和 + 枚举
排序+去重后的数组
预处理前i个位置需要鬼牌数量的前缀和
二分顺子中最后牌的位置
对于枚举的每个二分答案取 min(m, ans)
#include "bits/stdc++.h"
#include <numeric>
using namespace std;
#define int int64_t
void _solution()
{
int n, m, k;
cin >> n >> m >> k;
vector<int> a(n + 1);
for(int i = 1;i <= n;++i) cin >> a[i];
sort(a.begin() + 1, a.end());
n = unique(a.begin() + 1, a.end()) - a.begin() - 1;
vector<int> b(n + 1);
int lPtr = a[1];
for(int i = 2;i <= n;++i)
{
if(a[i] - lPtr != 1)
{
b[i] = b[i - 1] + a[i] - lPtr - 1;
}
else
{
b[i] = b[i - 1];
}
lPtr = a[i];
}
// for(int i = 1;i <= n;++i) cout << b[i] << ' '; cout << '\n';
//1 4 6 8
//0 2 3 4
auto IsBlue = [&](int x, int i) //二分最大x的位置
{
//k > b[x] - b[i] 可以增加最大牌的位置
//k == b[x] - b[i] 尽可能增长长度
//k < b[x] - b[i] 鬼牌不足 只能减少最大牌的位置
return k >= b[x] - b[i];
};
int ulRes = 0;
for(int i = 1;i <= n;++i)
{
// cout << a[i] << ' ';
int l = 0, r = n + 1;
while(l + 1 < r)
{
int _m = (r - l >> 1) + l;
if(IsBlue(_m, i)) l = _m;
else r = _m;
}
// cout << l << ' ';
int curRes = min(m, a[l] - a[i] + 1 + k - (b[l] - b[i]) );
// cout << curRes << "-\n";
ulRes = max(curRes, ulRes);
}
cout << ulRes << '\n';
return;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
_solution();
return 0;
}