Codeforces Round 966 (Div. 3)
A. Primary Task
#include <bits/stdc++.h>
using namespace std;
using vi = vector<int>;
void solve() {
string s;
cin >> s;
if (s.size() <= 2) {
cout << "NO\n";
return;
}
if (s[0] != '1' or s[1] != '0') {
cout << "NO\n";
return;
}
auto t = s.substr(2);
if (t.empty() or stoi(t) < 2 or t.front() == '0') {
cout << "NO\n";
return;
}
cout << "YES\n";
return;
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T;
cin >> T;
while (T--)
solve();
return 0;
}
B. Seating in a Bus
#include <bits/stdc++.h>
using namespace std;
using vi = vector<int>;
void solve() {
int n;
cin >> n;
vi a(n + 5);
bool f = true;
for (int i = 1, x; i <= n; i++) {
cin >> x;
if (i != 1 and a[x - 1] == 0 and a[x + 1] == 0) f = false;
a[x] = 1;
}
if (f) cout << "YES\n";
else cout << "NO\n";
return;
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T;
cin >> T;
while (T--)
solve();
return 0;
}
C. Numeric String Template
#include <bits/stdc++.h>
using namespace std;
using vi = vector<int>;
const int inf = INT_MAX / 2;
void solve() {
int n;
cin >> n;
vi a(n);
for (auto &i: a) cin >> i;
int m;
cin >> m;
for (string s; m; m--) {
cin >> s;
if (s.size() != n) {
cout << "NO\n";
continue;
}
map<int, set<char>> cnt1;
map<char, set<int>> cnt2;
for (int i = 0; i < n; i++) {
cnt1[a[i]].insert(s[i]);
cnt2[s[i]].insert(a[i]);
}
bool f = true;
for (auto [key, val]: cnt1)
if (val.size() > 1) f = false;
for (auto [key, val]: cnt2)
if (val.size() > 1) f = false;
if (f) cout << "YES\n";
else cout << "NO\n";
}
return;
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T;
cin >> T;
while (T--)
solve();
return 0;
}
D. Right Left Wrong
贪心,从左到右遍历,对于每一个L
找到最右侧没有被使用过的R
,求和的部分可以用前缀和优化。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using ldb = long double;
#define int i64
using vi = vector<int>;
void solve() {
int n;
cin >> n;
vi a(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
a[i] += a[i - 1];
string b;
cin >> b;
b = " " + b;
vi R;
for (int i = 1; i <= n; i++)
if (b[i] == 'R') R.push_back(i);
int res = 0;
for (int i = 1, x; i <= n; i++) {
if (b[i] != 'L') continue;
if (R.empty()) continue;
x = R.back(), R.pop_back();
if (x < i) continue;
res += a[x] - a[i - 1];
}
cout << res << "\n";
return;
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T;
for (cin >> T; T; T--)
solve();
return 0;
}
E. Photoshoot for Gorillas
二维前缀和算出每一格被多少个子矩形覆盖,然后贪心放置。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using ldb = long double;
const i32 inf = INT_MAX / 2;
const i64 INF = LLONG_MAX / 2;
#define int i64
using vi = vector<int>;
void solve() {
int n, m, k;
cin >> n >> m >> k;
vector a(n + 2, vi(m + 2));
for (int i = 1, x = k; x <= n; i++, x++)
for (int j = 1, y = k; y <= m; j++, y++)
a[i][j]++, a[i][y + 1]--, a[x + 1][j]--, a[x + 1][y + 1]++;
vi val;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
a[i][j] += a[i][j - 1] + a[i - 1][j] - a[i - 1][j - 1];
val.push_back(a[i][j]);
}
sort(val.begin(), val.end(), greater<>());
int w;
cin >> w;
vi b(w);
for (auto &i: b) cin >> i;
sort(b.begin(), b.end(), greater<>());
int res = 0;
for (int i = 0; i < w; i++)
res += b[i] * val[i];
cout << res << "\n";
return;
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T;
for (cin >> T; T; T--)
solve();
return 0;
}
F. Color Rows and Columns
首先考虑只有一个矩形的情况。
对于一个矩形,如果是\(1\times 1\)的矩形,则只能填这个一个格子,并获得\(2\)分。否则的话,一定是贪心的填满一个短边,并获得\(1\)分。所以对于一个矩形,我们可以贪心求出获得\(w\)分,需要操作\(v\)次。
这样的话,我们可以采用分组背包来解决,对于每一个矩形贪心求出最优解即可。
#include <bits/stdc++.h>
using namespace std;
using i32 = int32_t;
using i64 = long long;
using ldb = long double;
const i32 inf = INT_MAX / 2;
const i64 INF = LLONG_MAX / 2;
#define int i64
using vi = vector<int>;
void solve() {
int n, k;
cin >> n >> k;
vi f(k + 2, inf);
f[0] = 0;
for (int i = 1, x, y, v, w; i <= n; i++) {
cin >> x >> y, v = 0, w = 0;
auto g = f;
while (x > 0 and y > 0) {
if (x > y) swap(x, y);
if (x == 1 and y == 1) v += 1, w += 2, x = y = 0;
else v += x, w += 1, y--;
for (int j = w; j <= k + 1; j++)
g[j] = min(g[j], f[j - w] + v);
}
f = move(g);
}
int res = min(f[k], f[k + 1]);
if (res == inf) cout << "-1\n";
else cout << res << "\n";
return;
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T;
for (cin >> T; T; T--)
solve();
return 0;
}