Codeforces Round #650 (Div. 3)
B
计算偶数位置上的奇数 和 奇数位置上的偶熟 个数是否相等,
不相等的话,就不可能变成 \(good\)
相等的话,每次\(swap\) 一下消除一对,最小的操作数就是偶数(奇数)的个数
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while(t --) {
int n;
cin >> n;
vector<int> a(n,0);
for(int i = 0;i < n; ++i) cin >> a[i];
int cnt = 0,even = 0,odd = 0;
for(int i = 0;i < n; i += 2) {
if(a[i] % 2 != 0) even ++;
}
for(int i = 1;i < n; i += 2) {
if(a[i] % 2 != 1) odd ++;
}
if(even != odd) cout << "-1";
else cout << even ;
cout << endl;
}
return 0;
}
C
转化下思想,用 \(0\) 来找 \(1\) ,而不是傻傻的直接模拟
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin >> t;
while(t --) {
int n,k,cnt = 0;
char ch;
cin >> n >> k;
vector<int> a(n,0);
for(int i = 0;i < n; ++i) {
cin >> ch;
if(ch == '1') a[i] = 1;
else a[i] = 0;
}
for(int i = 0;i < n; ++i) {
if(a[i] == 0) {
int j = i + 1;
while(j < n && a[j] == 0 && j - i <= k) ++ j;
if(j - i > k || j == n) {
cnt ++;
i += k;
}
else i = j - 1;
}
else i += k;
}
cout << cnt << endl;
}
return 0;
}
参考
D
要找对方法模拟
每次找到一组 \(0\) ,\(b[]\) 中的其他值都减去这个位置,就更新了,而当前的 \(0\) 一定是最大值,在单词中找到,然后加到答案里面即可
#include <bits/stdc++.h>
using namespace std;
int num[60],dict[30];
bool st[60];
int n;
void word(int x) {
for(int i = 0;i < n; ++i) {
if(num[i]) num[i] -= abs(i - x);
}
}
int main() {
int t;
cin >> t;
string s;
while(t --) {
memset(num,0,sizeof num);
memset(dict,0,sizeof dict);
memset(st,0,sizeof st);
cin >> s >> n;
vector<char> str(n);
for(int i = 0;i < s.length(); ++i) dict[s[i] - 'a'] ++;
for(int i = 0;i < n; ++i) cin >> num[i];
while(1) {
bool flag = 1;
vector<int> v;
for(int i = 0;i < n; ++i) {
if(num[i] == 0 && st[i] == 0) {
v.push_back(i);
st[i] = 1;
flag = 0;
}
}
int idx = 0;
for(int i = 25;i >= 0; --i) {
if(dict[i]) {
if(dict[i] >= v.size()) {
idx = i;
dict[i] = 0;
break;
}
dict[i] = 0;
}
}
for(auto i : v) {
word(i);
str[i] = idx + 'a';
}
if(flag) break;
}
for(int i = 0;i < n; ++i) cout << str[i];
cout << endl;
}
return 0;
}
参考
E
二分 \(k\) 的因子,有好多小坑
yxc的那个模板不太会用,好像处理不了这种问题
这个二分模板很舒服
while(l <= r) {
int mid = l + r >> 1;
if(check(mid)) r = mid - 1;
else l = mid + 1;
}
#include <bits/stdc++.h>
using namespace std;
int num[30];
bool check(int x,int k) {
for(int i = 0;i < 26; ++i) {
x -= num[i] / k;
if(x <= 0) return 1;
}
return 0;
}
int main() {
int t;
cin >> t;
string s;
int n,k;
while(t --) {
memset(num,0,sizeof num);
cin >> n >> k >> s;
int ans = 0;
for(int i = 0;i < n; ++i) {
ans = max(ans,++ num[s[i] - 'a']);
}
for(int i = 2;i <= k; ++i) {
if(k % i != 0) continue;
int l = 1,r = n / i;
while(l <= r) {
int mid = l + r >> 1;
if(check(i,mid)) {
l = mid + 1;
ans = max(ans,mid * i);
}
else r = mid - 1;
}
}
cout << ans << endl;
}
}
参考
F
离散化一遍,找到最长连续子序列,\(n-ans\) 就是答案
因为最长连续子序列哪一块肯定不用动,只需要移动剩下的数字即可
#include <bits/stdc++.h>
using namespace std;
const int N = 3010;
int a[N],b[N];
int main() {
int t,n;
cin >> t;
while(t --) {
cin >> n;
for(int i = 0;i < n; ++i) {
cin >> a[i];
b[i] = a[i];
}
sort(b,b + n);
for(int i = 0;i < n; ++i) {
a[i] = lower_bound(b,b + n,a[i]) - b;
}
int ans = 0,cnt = 0;
while(cnt < n) {
int len = 0;
for(int i = 0;i < n; ++i) {
if(cnt == a[i]) {
cnt ++;
len ++;
}
}
ans = max(ans,len);
}
cout << n - ans<< endl;
}
return 0;
}
参考