题意:用给定数目的B尽可能的分割字符串R,使得连在一起的R的最大值最小。
分析:基于贪心的思路,把字符串R尽可能的平均分,当然可能会有剩余的情况,那么就把这剩余的R分别插入到已经配好的子字符串里。
代码:
//插到前面
#include <iostream>
using namespace std;
int main() {
int t;
cin >> t;
while(t--) {
int n, a, b;
cin >> n >> a >> b;
int t = a % (b + 1);
// 加到前面
for(int i = 1; i <= t; i++) {
for(int j = 1; j <= a / (b + 1) + 1; j++) cout << "R";
cout << "B";
}
for(int i = t + 1; i <= b + 1; i++) {
for(int j = 1; j <= a / (b + 1); j++) cout << "R";
if(i != b + 1) cout << "B";
}
cout << endl;
}
return 0;
}
// 插到后面
#include <iostream>
using namespace std;
void solve() {
int n, a, b;
cin >> n >> a >> b;
int t = a % (b + 1);
for(int i = 1; i <= b - t + 1; i++) {
for(int j = 1; j <= a / (b + 1); j++) cout << "R";
if(t || i != b + 1) cout << "B";
}
for(int i = 1; i <= t; i++) {
for(int j = 1; j <= a / (b + 1) + 1; j++) cout << "R";
if(i != t) cout << "B";
}
cout << endl;
}
int main() {
int t;
cin >> t;
while(t--) {
solve();
}
return 0;
}
题意:给定n个数字\(a_1\)、\(a_2\)...可以进行一种操作:\(a_i\)不变,其余位变为置反;求进行k次这种操作,使得该数组最大。(定义大小: 在数组a,b的第一个不同位,若a的该位为1,b相应位为0,则a > b);
分析:先进行k次取反操作,然后依次将0置为1,如果所以的0都置为1了,操作数k还有剩余,就一直对最末尾进行k次操作,如果k为偶数,那么不变,如果为奇数,那么最末尾置反。
代码:
#include <iostream>
#include <cstring>
using namespace std;
const int N = 2e5 + 10;
int cnt[N];
int n;
void solve() {
int n, k, ans = 0;
string s;
cin >> n >> k >> s;
if(k % 2) {
for(int i = 0; i < n; i++) {
if(s[i] == '1') s[i] = '0';
else s[i] = '1';
}
}
//cout << s << endl;
memset(cnt, 0, sizeof cnt);
for(int i = 0; i < n; i++) {
if(k == 0) break;
if(s[i] == '0') {
s[i] = '1';
cnt[i]++;
//cout << "i" << i << endl;
k--;
}
}
//cout << "k" << k << endl;
if(k) {
if(k % 2) s[n - 1] = '0';
cnt[n - 1] += k;
}
cout << s << endl;
for(int i = 0; i < n; i++) cout << cnt[i] << ' ';
cout << endl;
}
int main() {
int t;
cin >> t;
while(t--) {
solve();
}
return 0;
}
题意:给定n个由小到大的坐标\(x_1\)、\(x_2\)...起始位置在0,给定a,b, 可以进行两种操作:
1.移动位置由\(c_1\)到\(c_2\) 这将花费a * |\(c_1\) - \(c_2\)|。(能移动的前提是\(c_1\)、\(c_2\) 已经被占领
2.攻击一个坐标,当前位置为\(c_1\),攻击的坐标为\(c_2\),那么花费b * |\(c_1\) - \(c_2\)|。 但是在\(c_1\)]、\(c_2\)之间不能有未攻击的坐标(\(x_i\)), 求攻击所有所给坐标的最小花费。
分析:基于贪心:设当前点为\(x_1\),要移动的点为\(x_i\) 那么如果我要移动到\(x_i\)应该要满足:
$$ a * | x_1 - x_i | < (n - i) * b * |x_1 - x_i| $$那么化简得: $$ a < (n - i) * b $$
所以只要满足这个条件就可以移动
代码:
#include <iostream>
using namespace std;
#define int long long
const int N = 2e5 + 10;
int q[N];
void solve() {
int n, a, b;
cin >> n >> a >> b;
for(int i = 1; i <= n; i++) cin >> q[i];
int cost = 0;
int pos = 0;
for(int i = 1; i <= n; i++) {
cost += b * (q[i] - pos);
if(a / b < (n - i)) {
cost += a * (q[i] - pos);
pos = q[i];
}
}
cout << cost << endl;
}
signed main() {
int t;
cin >> t;
while(t--) {
solve();
}
return 0;
}
代码:(基于好友)
#include <iostream>
using namespace std;
#define int long long
const int N = 2e5 + 10;
int c[N];
void solve() {
int n, sum = 0;
cin >> n;
for(int i = 1; i <= n; i++) cin >> c[i], sum += c[i];
int t = sum / n;
for(int i = n; i && t; i--) {
if(c[i] == n) t--;
else {
c[i-t] += c[i];
c[i] = 0;
}
}
for(int i = 1; i <= n; i++) {
if(c[i]) cout << 1 << ' ';
else cout << 0 << ' ';
}
cout << endl;
}
signed main() {
int t;
cin >> t;
while(t--) {
solve();
}
return 0;
}