Codeforces Round 935 (Div. 3)

A. Setting up Camp

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;

void solve() {
    int a, b, c;
    cin >> a >> b >> c;
    int res = a + b / 3;
    b %= 3;
    if (b != 0) {
        if (c < 3 - b) {
            cout << "-1\n";
            return;
        }
        c -= 3 - b, res++;
    }
    res += ( c + 2 ) / 3 ;
    cout << res << "\n";
    return;
}


i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int TC;
    for (cin >> TC; TC; TC--) solve();
    return 0;
}

B. Fireworks

计算出每种烟花同时最多看多少个,然后相加即可。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = int64_t;

void solve() {
    i64 a, b, c;
    cin >> a >> b >> c , c ++;
    a = ( c + a - 1 ) / a;
    b = ( c + b - 1 ) / b;
    cout << a + b << "\n";
    return;
}


i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int TC;
    for (cin >> TC; TC; TC--) solve();
    return 0;
}

C. Left and Right Houses

可以直接枚举一下路的位置,然后后缀和处理一下。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = int64_t;

void solve() {
    int n;
    string s;
    cin >> n >> s;
    int l = 0, r = 0, ans;
    double p = 1e9;
    for (auto i: s) r += i == '1';
    for (int i = 0; i <= n; i++) {
        if (l >= (i + 1) / 2 and r >= (n - i + 1) / 2) {
            double t = abs(0.5 * n - i);
            if (p > t) p = t, ans = i;
        }
        if( i < n ) l += s[i] == '0' , r-= s[i] == '1';
    }
    cout << ans << "\n";
    return;
}


i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int TC;
    for (cin >> TC; TC; TC--) solve();
    return 0;
}

D. Seraphim the Owl

首先我们要从前\(m\)个位置选择一个点作为终点,然后从起点到终点的过程中每个点可以任意选\(a,b\)但是终点只能是\(a\)

为什么过程中可以任意选\(a,b\),对于每个点,如果你直接走过去就是\(b\),如果停留一下就是\(a\)

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = int64_t;

using vi = vector<i64>;
const i64 inf = 1e18;


void solve() {
    int n, m;
    cin >> n >> m;
    vi a(n + 1), b(n + 2);
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (int i = 1; i <= n; i++)
        cin >> b[i], b[i] = min(b[i], a[i]);
    for (int i = n - 1; i >= 1; i--)
        b[i] += b[i + 1];
    i64 res = inf;
    for (int i = 1; i <= m; i++)
        res = min(res, a[i] + b[i + 1]);
    cout << res << "\n";
    return;
}


i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int TC;
    for (cin >> TC; TC; TC--) solve();
    return 0;
}

E. Binary Search

我感觉是可以只通过一次操作就一定可以实现要求。

根据这个猜想,交换的一个点应该是目标数字,所以我枚举另一个点,然后进行交换,最后再模仿题目的二分进行一次 check

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;
using ui64 = uint64_t;

#define int long long

using vi = vector<int>;
using pii = pair<int, int>;

const int mod = 998244353;
const int inf = 1e18;

const vi dx = {0, 0, 1, -1, 1, 1, -1, -1}, dy = {1, -1, 0, 0, 1, -1, 1, -1};

void solve() {
    int n, x;
    cin >> n >> x;
    vi p(n + 1);
    int y;
    for (int i = 1; i <= n; i++) {
        cin >> p[i];
        if (p[i] == x) y = i;
    }
    for (int i = 1, l, r; i <= n; i++) {
        swap(p[i], p[y]);
        l = 1, r = n + 1;

        for (int m; r - l != 1;) {
            m = (l + r) / 2;
            if (p[m] <= x) l = m;
            else r = m;
        }
        if (p[l] == x) {
            cout << "1\n" << y << " " << i << "\n";
            return;
        }
        swap(p[i], p[y]);
    }
    return;
}

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}

F. Kirill and Mushrooms

强度等于\(k\times val\),其中\(k\)是我选择的个数,\(val\)是选择的最小值。

如果我枚举出\(k\)就可以确定那些蘑菇的值为 0,然后在剩下的蘑菇中贪心的选择最大的\(k\)个,这样就可以知道\(val\)

我用multiset<int>维护两个集合,一个是cnt表示当前不为0 且没有被选到的蘑菇,q是当前被选到的最大的\(k\)个蘑菇。

然后从小到大枚举\(k\),每次都从\(cnt\)中取最大值填入到q中,直到q.size() == k。然后随着选择数量增大,就要是的一些蘑菇变为0,也就说要从两个集合中删掉一些蘑菇,每次删除时优先从cnt中删除即可。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;
using ui64 = uint64_t;

#define int long long

using vi = vector<int>;
using pii = pair<int, int>;

const int mod = 998244353;
const int inf = 1e18;

void solve() {
    int n;
    cin >> n;
    multiset<int> cnt, q;
    vi a(n + 1);
    vi p(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> a[i], q.insert(a[i]);

    for (int i = 1; i <= n; i++)
        cin >> p[i];
    int res = -inf, val = -inf;
    for (int i = 1, v, x; i <= n; i++) {
        while (not q.empty() and cnt.size() < i) {
            x = *q.rbegin();
            cnt.insert(x), q.erase(q.find(x));
        }
        if (cnt.size() < i) break;
        v = *cnt.begin() * i;
        if (v > res) res = v, val = i;
        
        if (q.count(a[p[i]]))
            q.erase(q.find(a[p[i]]));
        else
            cnt.erase(cnt.find(a[p[i]]));
    }
    cout << res << " " << val << "\n";
    return;
}

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--)
        solve();
    return 0;
}

G. Cook and Porridge

这个题目实际上要求维护一个序列,但是这个序列要实现一个插队的功能。

如果把重新入队的人单独放在一个优先队列内。然后提前维护一个\(k_i\)的后缀最大值\(suf_i\)

如果没时刻我取出队列的第一个和优先队列中的第一个。然后比较一下后缀最值和优先队列队首权值的大小,如果后缀最值更大说明不会插队到当前的人前面,则队首出队,否则优先队列出队。

#include <bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = int64_t;


using vi = vector<i64>;
using pii = pair<i64, i64>;

const i64 inf = 1e18;

#define int i64

void solve() {
    int n, d;
    cin >> n >> d;
    vector<pii> a(n);
    for (auto &[k, s]: a) cin >> k >> s;
    vi suf(n + 1);
    for (int i = n - 1; i >= 0; i--)
        suf[i] = max(a[i].first, suf[i + 1]);
    vector<vi> que(d + 1);
    int t = 0;
    set<array<int, 4>> st;
    for (int time = 1; time <= d; time++) {
        if (not st.empty() and prev(st.end())->at(0) > suf[t]) {
            auto [k, tim, s, id] = *prev(st.end());
            s = -s;
            st.erase(prev(st.end()));
            if (time + s <= d)
                que[time + s].push_back(id);
        } else {
            auto [kt, st] = a[t];
            if (time + st <= d)
                que[time + st].push_back(t);
            t++;
        }
        if (t == n) {
            cout << time << "\n";
            return;
        }
        for (auto id: que[time]) {
            auto [ki, si] = a[id];
            st.insert({ki, -time, -si, id});
        }
    }
    cout << "-1\n";
    return;
}

i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int TC;
    for (cin >> TC; TC; TC--) solve();
    return 0;
}
posted @ 2024-03-21 21:42  PHarr  阅读(43)  评论(0编辑  收藏  举报