Codeforces Round 933 (Div. 3)

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;
}
posted @ 2024-03-12 22:29  value0  阅读(93)  评论(0)    收藏  举报