诈骗系列之-CF2059B
闲话
本文同步发布在 cnblogs。
诈骗好题,因数组开小吃掉两发罚时。
分两种情况:
\(n = k\),比较简单,暴力模拟即可。
\(n \not = k\),此时思考一个问题:
如何使成本最小?
答案显而易见,设 \(a_i = x\),则使 \(a_{i + 1} \not = x + 1\) 即可。
于是我们得到这样的代码:
#include<bits/stdc++.h>
using namespace std;
int t, n, k, a[200005];
int main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> t;
while(t --){
cin >> n >> k;
for(int i = 1; i <= n; i ++){
cin >> a[i];
}
if(n == k){
int flag = 1, maxn = 0;
for(int i = 2; i <= n; i += 2){
maxn = max(maxn, a[i]);
if(a[i] != i / 2){
cout << i / 2 << "\n";
flag = 0; break;
}
}
if(flag) cout << maxn + 1 << "\n";
}
else{
int ans = 2e9;
for(int i = 1; i < n; i ++){
if(a[i + 1] != a[i] + 1){
ans = i + 1;
break;
}
}
cout << ans << "\n";
}
}
return 0;
}
毫无疑问,这是错的。
思考错在哪里,刚才我们只是找了中间部分是否会断,但并没有提到起始位置。
如果我们能使它刚开始就不符合要求,答案就是最小的 \(1\)。由于后面还需要分块,简单进行数学运算可得,我们只能在前面 \(n - k + 2\) 处查找 \(a_i \not = 1\) 的数,注意 \(i \not = 1\),因为 \(1\) 只能在奇数块。
正确代码如下:
#include<bits/stdc++.h>
using namespace std;
int t, n, k, a[200005];
int main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> t;
while(t --){
cin >> n >> k;
for(int i = 1; i <= n; i ++){
cin >> a[i];
}
if(n == k){
int flag = 1, maxn = 0;
for(int i = 2; i <= n; i += 2){
maxn = max(maxn, a[i]);
if(a[i] != i / 2){
cout << i / 2 << "\n";
flag = 0; break;
}
}
if(flag) cout << maxn + 1 << "\n";
}
else{
int ans = 2e9;
for(int i = 1; i < n; i ++){
if(a[i + 1] != a[i] + 1){
ans = i + 1;
break;
}
}
for(int i = 2; i <= n - k + 2; i ++){
if(a[i] != 1){
ans = 1;
break;
}
}
cout << ans << "\n";
}
}
return 0;
}
posted on 2025-02-03 00:51 zhangzirui66 阅读(24) 评论(0) 收藏 举报