Codeforces Round #617 (Div. 3) A~E
比赛链接:Here
1296A. Array with Odd Sum
题意:给了 \(n\) 个数,现在就是说可以选择两个数让其中一个的值等于另一个的值.
这种操作无限次 问是不是能让这n个数操作后的总和为奇数
题解:我们都知道奇数+奇数等于偶数 所以奇数=偶数-奇数 所以只要有奇数有偶数就可以
【AC Code】
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int _; for (cin >> _; _--;) {
int n;
cin >> n;
int odd = 0, even = 0, sum = 0;
for (int i = 0, x; i < n; ++i) {
cin >> x; sum += x;
if (x & 1) odd += 1;
else even += 1;
}
cout << (((odd && even) || sum & 1) ? "YES\n" : "NO\n");
}
}
1296B. Food Buying
题意:给了 \(n\) 块钱 每花 \(10\) 块 都能得到一块 问可以当多少钱花
题解:经典瓶盖兑换问题,争对 \(1e9\) 的数据范围可以直接暴力跑
【AC Code】
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int _; for (cin >> _; _--;) {
ll n;
cin >> n;
int cnt = n;
while (n >= 10) {
cnt += n / 10;
n = n % 10 + n / 10;
}
cout << cnt << "\n";
}
}
1296C. Yet Another Walking Robot
题意:给长度为 \(n\) 的字符串 让你删去一个区间的坐标 不影响终点 区间越小越好
题解:map标记下走过的点 走过了后面再走到 存下来 排序 输出区间长度最短的就好
【AC Code】
using pii = pair<int, int>;
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int _; for (cin >> _; _--;) {
int n;
string s;
cin >> n >> s;
map<pii, int>mp;
bool f = 0;
int x = 0, y = 0;
mp[ {x, y}] = 1;
vector<pii> v;
for (int i = 0; i < n; ++i) {
if (s[i] == 'L') x -= 1;
if (s[i] == 'R') x += 1;
if (s[i] == 'U') y += 1;
if (s[i] == 'D') y -= 1;
if (mp[ {x, y}]) v.push_back({mp[{x, y}], i + 1});
mp[ {x, y}] = i + 2;
}
if (v.empty()) {
cout << "-1\n";
continue;
}
sort(v.begin(), v.end());
cout << v[0].first << " " << v[0].second << "\n";
}
}
1296D. Fight with Monsters
题意:你和你的对手轮流打怪,对于每只怪 都是你先手 你对手后手
有 \(n\) 个怪,你攻击力\(a\),你对手攻击力\(b\),怪的血 \(hp_i\) ,现在你有\(k\)个机会,可以让你对手忽略他出手的回合,就是说你用一次机会 你就能连续打两次 连续用两次次机会就能连续打三次,用的总机会次数小于等于 \(k\) 现在问最多有多少只怪 只被你终结的 就是你打最后一下让 \(hp_i\le0\)
题解:贪心,
显然 先对 \(hp_i\) 取模 \((a+b)\) 如果能被整除的话就保留 \(hp_i=a+b\) 这样操作之后 每一只怪的先手还是你,然后对剩余的血量进行排序 对于 \(hp_i\le a\) 的 你打一下他就 gg 那么答案就是 \(ans+1\)
对于一下子不打死的呢,我们已经按血量排序了 那么肯定把机会优先用掉,
你用 \(k\) 次机会,怪会被 \(k+1\) 次的 \(a\) 的血量
所以我们计算 \(r=hp_i/a\) 看需要打几次 这里要注意需要看是不是整除
整除的话 需要 r–,因为用 \(k\) 次机会 可以连续打 \(k+1\) 下 不能整除就是需要用r次机会刚好
【AC Code】
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n, a, b, k;
cin >> n >> a >> b >> k;
int c = a + b;
vector<int>q(n + 1);
for (int i = 1; i <= n; ++i) {
cin >> q[i];
q[i] %= c;
if (!q[i]) q[i] = c;
}
sort(q.begin() + 1, q.end());
int ans = 0;
for (int i = 1; i <= n; i++) {
// cout << i << " " << q[i] << "\n";
if (q[i] <= a) ans++;
else {
int r = q[i] / a;
if (q[i] % a == 0) r--;
if (r <= k) k -= r, ans++;
else break;
}
}
cout << ans << "\n";
}
1296E. String Coloring
(Easy version)
题意:让你给题中给定的字符串 的每个字符染色 \(0\) 或者 \(1\),然后不同颜色的字符可以交换 问你是不是有一种染色方案 可以让给定的字符串进行任意次交换后是有序的
题解:因为只有两种颜色可以用来涂相同颜色彼此不能交换所以同一种颜色组成的序列绝对是非严格递增的所以只要看是不是能把序列分成两个非严格递增的序列即可
【AC Code】
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n; string s;
cin >> n >> s;
vector<int>v(n, 0);
char tmp = 'a';
for (int i = 0; i < n; ++i)
if (s[i] >= tmp) tmp = s[i], v[i] = 1;
tmp = 'a';
for (int i = 0; i < n; i++)
if (!v[i] && s[i] >= tmp) tmp = s[i], v[i] = 2;
for (int i = 0; i < n; i++)
if (!v[i]) return printf("NO\n"), 0;
cout << "YES\n";
for (int i = 0; i < n; ++i) cout << v[i] - 1;
}
(Hard version)
意思和E1一样 只不过可以用不同的颜色,要求用的颜色越少越好
我们由E1知道 要两个非严格递增序列组成即可,那么E2就是看序列能不能由ans个非严格递增序列组成 ans越小越好。
最后就一直找即可
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n; string s;
cin >> n >> s;
vector<int>v(n, 0);
int ans = 1, num = 0;
while (num < n) {
int l = 'a';
for (int i = 0; i < n; i++)
if (!v[i] && s[i] >= l) l = s[i], v[i] = ans, num++;
ans++;
}
cout << ans - 1 << "\n";
for (int i = 0; i < n; i++) cout << v[i] << " ";
}