Codeforces Round 933 (Div. 3)

value0發表於2024-03-12

Codeforces Round 933 (Div. 3)

A - Rudolf and the Ticket

解題思路:

暴力。

程式碼:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;

void solve()
{
    int n, m, k;
    cin >> n >> m >> k;
    vector<int> a(n + 1), b(m + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    for (int i = 1; i <= m; i++)
    {
        cin >> b[i];
    }
    int cnt = 0;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            if (a[i] + b[j] <= k)
            {
                cnt++;
            }
        }
    }
    cout << cnt << endl;
}

int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

B - Rudolf and 121

解題思路:

從左到右變成\(0\)即可。

程式碼:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;

void solve()
{
    int n;
    cin >> n;
    vector<ll> a(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    for (int i = 2; i <= n - 1; i++)
    {
        if (a[i - 1] < 0)
        {
            puts("NO");
            return;
        }
        a[i] -= a[i - 1] * 2;
        a[i + 1] -= a[i - 1];
        a[i - 1] = 0;
    }
    for (int i = 1; i <= n; i++)
    {
        if (a[i] != 0)
        {
            puts("NO");
            return;
        }
    }
    puts("YES");
}

int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

C - Rudolf and the Ugly String

解題思路:

\(mapie,map, pie\)都一次能消掉。

程式碼:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;

void solve()
{
    int n;
    cin >> n;
    string s;
    cin >> s;
    s = ' ' + s;
    int cnt = 0;
    for (int i = 1; i <= n; i++)
    {
        if (i + 4 <= n)
        {
            string t = s.substr(i, 5);
            if (t == "mapie")
            {
                cnt++;
                i = i + 4;
                continue;
            }
        }
        if (i + 2 <= n)
        {
            string t = s.substr(i, 3);
            if (t == "map" || t == "pie")
            {
                cnt++;
                i = i + 2;
            }
        }
    }
    cout << cnt << endl;
}

int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

D - Rudolf and the Ball Game

解題思路:

\(O(nm)\),直接暴力模擬轉移。

程式碼:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;

void solve()
{
    int n, m, x;
    cin >> n >> m >> x;
    vector<bool> dp(n + 1, false);
    dp[x] = true;
    for (int j = 1; j <= m; j++)
    {
        vector<bool> cur(n + 1, false);
        int d;
        char t;
        cin >> d >> t;
        if (t == '0')
        {
            for (int i = 1; i <= n; i++)
            {
                int idx = (i - 1 + d) % n + 1;
                cur[idx] = cur[idx] | dp[i];
            }
        }
        else if (t == '1')
        {
            for (int i = 1; i <= n; i++)
            {
                int idx = (((i - 1 - d) % n) + n) % n + 1;
                cur[idx] = cur[idx] | dp[i];
            }
        }
        else
        {
            for (int i = 1; i <= n; i++)
            {
                int idx = (((i - 1 - d) % n) + n) % n + 1;
                cur[idx] = cur[idx] | dp[i];
                idx = (i - 1 + d) % n + 1;
                cur[idx] = cur[idx] | dp[i];
            }
        }
        dp = cur;
    }
    vector<int> ans;
    for (int i = 1; i <= n; i++)
    {
        if (dp[i])
        {
            ans.push_back(i);
        }
    }
    cout << ans.size() << endl;
    for (auto c : ans)
    {
        cout << c << ' ';
    }
    cout << endl;
}

int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

E - Rudolf and k Bridges

解題思路:

單調佇列最佳化\(dp\)求取每一列的建橋的最小花費。然後取最小連續段。

程式碼:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;

void solve()
{
    int n, m, k, d;
    cin >> n >> m >> k >> d;
    vector<vector<ll>> a(n + 1, vector<ll>(m + 1, 0));
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            cin >> a[i][j];
            if (j != 1 && j != m)
            {
                a[i][j]++;
            }
        }
    }
    vector<ll> ans(1, 0);
    for (int i = 1; i <= n; i++)
    {
        vector<ll> q(m + 1);
        int hh = 0;
        int tt = -1;
        vector<ll> dp(m + 1);
        for (int j = 1; j <= m; j++)
        {
            while (hh <= tt && j - (q[hh]) > d + 1)
            {
                hh++;
            }
            dp[j] = a[i][j];
            if (hh <= tt)
            {
                dp[j] += dp[q[hh]];
            }
            // cerr << i << ' ' << j << ' ' << dp[j] << endl;
            while (hh <= tt && dp[j] < dp[q[tt]])
            {
                tt--;
            }
            q[++tt] = j;
        }
        // cerr << dp[m] << endl;
        ans.push_back(dp[m]);
    }
    for (int i = 1; i <= n; i++)
    {
        ans[i] += ans[i - 1];
    }
    ll res = 1e18;
    for (int i = 1; i <= n; i++)
    {
        if (i >= k)
        {
            res = min(res, ans[i] - ans[i - k] + k * 2);
        }
    }
    cout << res << endl;
}

int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

F - Rudolf and Imbalance

解題思路:

找到最大間距和次大間距。

如果最大間距不止一個,答案就是最大間距。

否則想要減小最大間距,就是要往最大間距之間添數字,對於每個\(d\)找能將間距儘量均分,然後和次大間距取較小。

程式碼:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;

void solve()
{
    int n, m, k;
    cin >> n >> m >> k;
    vector<ll> a(n + 1), d(m + 1), f(k + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    for (int i = 1; i <= m; i++)
    {
        cin >> d[i];
    }
    for (int i = 1; i <= k; i++)
    {
        cin >> f[i];
    }
    sort(a.begin() + 1, a.end());
    sort(d.begin() + 1, d.end());
    sort(f.begin() + 1, f.end());
    ll dist = -1;
    ll sd = -1;
    int cnt = 0;
    ll l = 0;
    ll r = 0;
    for (int i = 2; i <= n; i++)
    {
        ll t = a[i] - a[i - 1];
        if (t > dist)
        {
            if (dist != -1)
            {
                sd = dist;
            }
            dist = t;
            cnt = 1;
            l = a[i - 1];
            r = a[i];
        }
        else if (t == dist)
        {
            cnt++;
            sd = dist;
        }
        else
        {
            if (sd < t)
            {
                sd = t;
            }
        }
    }
    if (cnt > 1)
    {
        cout << dist << endl;
        return;
    }
    // cerr << l << ' ' << sd << endl;
    ll ans = dist;
    ll mid = (l + r + 1) / 2;
    for (int i = 1; i <= m; i++)
    {
        ll x = mid - d[i];
        auto it = lower_bound(f.begin() + 1, f.end(), x);
        if (it != f.end())
        {
            x = *it;
            ll t = d[i] + x;
            if (t >= l && t <= r)
            {
                ans = min(ans, max(r - t, t - l));
                if (sd != -1)
                {
                    ans = max(ans, sd);
                }
            }
        }
        if (it != f.begin() + 1)
        {
            it--;
            x = *it;
            ll t = d[i] + x;
            if (t >= l && t <= r)
            {
                ans = min(ans, max(r - t, t - l));
                if (sd != -1)
                {
                    ans = max(ans, sd);
                }
            }
        }
        // cerr << i << ' ' << d[i] << ' ' << x << endl;
    }
    cout << ans << endl;
}

int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

G - Rudolf and Subway

解題思路:

根據某些點或者邊的分類特點減虛點。

將原圖轉化到和虛點相連的圖,然後在上面操作。

本題將點與顏色虛點建邊,點到顏色單向邊權值為\(1\),顏色向點建單向邊權值為\(0\)

\(01bfs\)

程式碼:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;

void solve()
{
    map<int, int> mp;
    int n, m;
    cin >> n >> m;
    vector<vector<pii>> e(n + m + 1, vector<pii>());
    for (int i = 1; i <= m; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        if (mp.find(c) == mp.end())
        {
            mp[c] = ++n;
        }
        c = mp[c];
        e[a].push_back({c, 1});
        e[c].push_back({a, 0});
        e[b].push_back({c, 1});
        e[c].push_back({b, 0});
    }
    deque<int> q;
    int st, ed;
    cin >> st >> ed;
    q.push_front(st);
    vector<ll> dist(n + 1, inf);
    vector<bool> vis(n + 1, false);
    dist[st] = 0;
    while (q.size())
    {
        auto u = q.front();
        q.pop_front();
        if (vis[u])
        {
            continue;
        }
        vis[u] = true;
        for (auto t : e[u])
        {
            auto v = t.fi;
            auto w = t.se;
            // cerr << u << ' ' << v << endl;
            if (dist[v] > dist[u] + w)
            {
                dist[v] = dist[u] + w;
                if (w)
                {
                    q.push_back(v);
                }
                else
                {
                    q.push_front(v);
                }
            }
        }
    }
    cout << dist[ed] << endl;
}

int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

相關文章