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;
}
posted @ 2024-08-21 15:06  PHarr  阅读(35)  评论(0编辑  收藏  举报