CF R872 div.2
C
首先发现第三种操作要去个重,剩下的 \(x_i\) 的个数和就是最劣答案,现在思考如何用前两种操作使答案变优。
不难发现可以枚举每一个 \(x_i\),再考虑 \(1 \sim (x_i-1)\) 和 \((x_i+1) \sim m\) 中有多少空位,空位即是总位置数减区间内\(x_i\) 个数。
空位和操作 \(1,2\) 取 \(min\),即为可增加的答案。时间复杂度 \(O(nlogn)\),需要排序。
思路还是好想,代码恶心,写了好久。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, m, a[N];
void solve(){
cin >> n >> m;
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
vector<int> b;
int left = 0, right = 0;
for(int i = 1; i <= n; i++){
if(a[i] == -1) left ++;
if(a[i] == -2) right ++;
if(a[i] > 0) b.push_back(a[i]);
}
sort(b.begin(), b.end());
b.erase(unique(b.begin(), b.end()), b.end());
int nn = b.size();
int ans = max(min(left + nn, m), min(right + nn, m)), cnt = 1;
for(auto t : b){
int l = t - cnt;
int r = m - t - (nn - cnt);
ans = max(ans, nn + min(l, left) + min(r, right));
cnt ++;
}
cout << ans << endl;
}
int main(){
int T; cin >> T;
while(T --)
solve();
return 0;
}
D