A - Add Plus Minus Sign
题意:给出01字符串,可以在每两个字符中间任意添加‘+’,‘-’。最后要使表达式的绝对值最小
思路:设表达式的值为\(cnt\),若当前\(cnt\)大于\(0\),不管是0,还是1,都要添加‘-’,如果是1,那么cnt--
若当前\(cnt\)小于等于\(0\),不管是0,还是1,都要添加‘+’,如果是1,那么cnt++
void solve() {
int n;
cin >> n;
string s;
cin >> s;
int cnt = 0;
string st;
if (s[0] == '1') cnt ++;
for (int i = 1; i < s.size(); i ++) {
if (cnt > 0) {
st += '-';
if (s[i] == '1') cnt --;
}
else {
st += '+';
if (s[i] == '1') cnt ++;
}
}
cout << st << endl;
}
\[\]B - Coloring
题意:给出n个格子,每个格子都要涂上颜色,给出m种颜色,每种颜色有\(a_i\)个,其中每k个格子不能有相同颜色,问是否有满足条件的答案
思路:将n个格子分为k份,每一份只涂k种不同颜色。
设n / t为 \(rd\) , n % t为 \(late\) ,\(late\)表示\(a_i\)最多有\(rd + 1\),且数量不超过\(late\)。
若\(a_i\)大于\(rd + 1\),说明不可能满足条件,NO。若\(a_i\)等于\(rd + 1\)的数目多于\(late\)也不满足条件,NO。否则YES
void solve() {
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= m; i ++) {
cin >> a[i];
}
sort(a + 1, a + 1 + m, greater<int>());
int late = n % k, rd = n / k;
bool ok = 1;
for (int i = 1; i <= m; i ++) {
if (a[i] <= rd) continue;
else {
if (late && a[i] - 1 == rd) {
late --;
continue;
}else {
ok = 0;
break;
}
}
}
if (ok) cout << "YES" << endl;
else cout << "NO" << endl;
}
\[\]C - Ice and Fire
题意:共有\(n\)个人和\(n - 1\)场比赛,第\(i\)个人的能力值是\(i\),\(n - 1\)场比赛规则由01字符串决定,0表示能力值小的获胜,1表示能力值大的获胜。只要场上多于1一个人,就继续根据字符串的顺序进行对战。求人数从\(2\) ~ \(n\),每轮最多有多少人获胜。
思路:根据数据和推算可知,每轮最后一个字符可以将一个人踢出获胜序列。如1 2 3 4, 比赛规则是001,最后一个字符是1,则1绝不可能获胜。
那么若是后缀有连续的0或1,则可以连续限定范围。故每轮只需要统计后缀上最大的0或1的数量\(t\),每轮总个数减去\(t\)即为所求。
void solve() {
int n;
cin >> n;
string s;
cin >> s;
int cnt1 = 0, cnt0 = 0;
for (int i = 0; i < n - 1; i ++) {
if (s[i] == '0') {
cnt1 = 0;
cnt0 ++;
} else {
cnt1 ++;
cnt0 = 0;
}
cout << i + 2 - max(cnt1, cnt0) << ' ';
}
cout << endl;
}
\[\]D - Same Count One
题意:给出n个长度为m的01字符串,可以对不同的两个字符串交换同一位置的字符,问是否能通过操作,使每个字符串中的1的数量相等。如果不能则输出-1。
思路:先统计\(n * m\)个字符中1的数量\(sum\)和每个字符串中1的数量\(s_i\)。若\(sum\) / \(n\) != 0说明不可能满足条件,输出-1。
若满足条件,按列枚举\(s_i\),\(ave = sum / n\),将小于\(ave\)和大于\(ave\)的行放入不同集合。然后两两匹配。最后输出即可。
struct ans{
int x, y, z;
};
//注意观察N的大小
void solve() {
int n, m;
cin >> n >> m;
vector<vector<int>> v(n + 1, vector<int>(m + 1));
int sum = 0; //统计总共1的个数
vector<int> s(n + 1); //统计每行1的个数
for (int i = 1; i <= n; i ++) {
s[i] = 0;
for (int j = 1; j <= m; j ++) {
cin >> v[i][j];
sum += v[i][j];
s[i] += v[i][j];
}
}
if (sum % n != 0) {
cout << -1 << endl;
return ;
}
vector<ans> res; //答案数组
vector<int> big, small;
int ave = sum / n;
for (int i = 1; i <= m; i ++) {
for (int j = 1; j <= n; j ++) {
if (s[j] < ave && v[j][i] == 0) small.push_back(j);
if (s[j] > ave && v[j][i] == 1) big.push_back(j);
}
for (int j = 0; j < min(big.size(), small.size()); j ++) {
s[big[j]] --, s[small[j]] ++;
res.push_back({big[j], small[j], i});
}
small.clear(), big.clear();
}
cout << res.size() << endl;
for (auto i : res) cout << i.x << ' ' << i.y << ' ' << i.z << endl;
}