AtCoder Beginner Contest 338

AtCoder Beginner Contest 338

A - Capitalized?

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;

void solve()
{
    string s;
    cin >> s;
    int n = s.size();
    for (int i = 0; i < n; i++)
    {
        if (i == 0)
        {
            if (s[i] >= 'a' && s[i] <= 'z')
            {
                puts("No");
                return;
            }
        }
        else
        {
            if (s[i] >= 'A' && s[i] <= 'Z')
            {
                puts("No");
                return;
            }
        }
    }
    puts("Yes");
}

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

    return 0;
}

B - Frequency

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;

void solve()
{
    string s;
    cin >> s;
    vector<int> cnt(40);
    int a = 0;
    for (auto c : s)
    {
        cnt[c - 'a']++;
        a = max(a, cnt[c - 'a']);
    }
    for (int i = 0; i < 30; i++)
    {
        if (a == cnt[i])
        {
            char c = i + 'a';
            cout << c << endl;
            return;
        }
    }
}

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

    return 0;
}

C - Leftover Recipes

解题思路:

观察数据范围,选择枚举制造\(A\)菜的数量。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;

void solve()
{
    int n;
    cin >> n;
    vector<ll> a(n + 1), b(n + 1), q(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> q[i];
    }
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    for (int i = 1; i <= n; i++)
    {
        cin >> b[i];
    }
    ll ans = 0;
    for (int i = 0; i <= 1e6 + 1; i++)
    {
        vector<ll> t = q;
        bool f = true;
        for (int j = 1; j <= n; j++)
        {
            ll cur = i * a[j];
            if (cur <= t[j])
            {
                t[j] -= cur;
            }
            else
            {
                f = false;
                break;
            }
        }
        if (!f)
        {
            // cout << i << endl;
            break;
        }
        ll res = 1e18;
        for (int j = 1; j <= n; j++)
        {
            if (b[j] > 0)
            {
                res = min(res, t[j] / b[j]);
            }
        }
        ans = max(ans, res + i);
    }
    cout << ans << endl;
}

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

    return 0;
}

D - Island Tour

解题思路:

\(a\to b\),一共就两个方向,也就是两种走法。

我们先在环上,计算出最短走法。对于该走法,使用差分数组,记录每条边被经过了多少次,以及经过该边的路径长度总和。

接下来,我们枚举删去边。

如果我们删去改变,意味着,凡是经过改变的路径全部不可走。此时,只能走另一个反向。

假设经过边\(i\)的路径长度之和为\(b[i]\),路径数量为\(c[i]\),则全部路径反走的长度之和为\(n * c[i] - b[i]\)

因为正反两个走法的长度之和为\(n\)

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;

void solve()
{
    int n, m;
    cin >> n >> m;
    vector<ll> a(max(n, m) + 10);
    vector<ll> b(max(n, m) + 10), c(max(n, m) + 10);
    ll sum = 0;
    for (int i = 1; i <= m; i++)
    {
        cin >> a[i];
        if (i > 1)
        {
            if (a[i] > a[i - 1])
            {
                int x = a[i] - a[i - 1];
                int y = a[i - 1] + n - a[i];
                if (x < y)
                {
                    sum += x;
                    b[a[i - 1]] += x;
                    b[a[i]] -= x;
                    c[a[i - 1]] += 1;
                    c[a[i]] -= 1;
                }
                else if (x >= y)
                {
                    sum += y;
                    if (a[i - 1] != 1)
                    {
                        b[1] += y;
                        b[a[i - 1]] -= y;
                        c[1] += 1;
                        c[a[i - 1]] -= 1;
                    }
                    b[a[i]] += y;
                    c[a[i]] += 1;
                }
            }
            else
            {
                int x = a[i - 1] - a[i];
                int y = a[i] + n - a[i - 1];
                if (x < y)
                {
                    sum += x;
                    b[a[i]] += x;
                    b[a[i - 1]] -= x;
                    c[a[i]] += 1;
                    c[a[i - 1]] -= 1;
                }
                else if (x >= y)
                {
                    sum += y;
                    if (a[i] != 1)
                    {
                        b[1] += y;
                        b[a[i]] -= y;
                        c[1] += 1;
                        c[a[i]] -= 1;
                    }
                    b[a[i - 1]] += y;
                    c[a[i - 1]] += 1;
                }
            }
        }
    }
    ll res = 0;
    ll ans = 1e18;
    for (int i = 1; i <= n; i++)
    {
        b[i] += b[i - 1];
        c[i] += c[i - 1];
        res = c[i] * n - b[i];
        ans = min(ans, sum + res - b[i]);
    }
    cout << ans << endl;
}

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

    return 0;
}

E - Chords

解题思路:

我们将每条连线表述为\((l,r)\),其中\(l < r\)

相交条件就是存在一对连线\((l_1,r_1),(l_2,r_2)\),有\(l_1 < l_2 < r_1,r_2 > r_1\)

所以,我们先排序。

对于第\(i\)条连线,找到所有满足\(l_i <l <r_i\)的连线,然后取区间中最大的\(r\)\(r_i\)比较,存在符合则存在相交。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;

void solve()
{
    int n;
    cin >> n;
    vector<pii> v(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> v[i].fi >> v[i].se;
        if (v[i].fi > v[i].se)
        {
            swap(v[i].fi, v[i].se);
        }
    }
    sort(v.begin() + 1, v.end());
    vector<vector<int>> f(n + 10, vector<int>(22));
    for (int j = 0; j <= 20; j++)
    {
        for (int i = 1; i + (1ll << j) - 1 <= n; i++)
        {
            if (j == 0)
            {
                f[i][j] = v[i].se;
            }
            else
            {
                f[i][j] = max(f[i][j - 1], f[i + (1ll << (j - 1))][j - 1]);
            }
        }
    }

    auto get = [&](int l, int r)
    {
        int len = r - l + 1;
        int k = log(len) / log(2);
        return max(f[l][k], f[r - (1ll << k) + 1][k]);
    };

    for (int i = 1; i <= n; i++)
    {
        auto idx = lower_bound(v.begin() + 1, v.end(), (pii){v[i].se, -1}) - v.begin() - 1;
        int l = i + 1;
        int r = idx;
        if (l > r)
        {
            continue;
        }
        ll val = get(l, r);
        if (val > v[i].se)
        {
            puts("Yes");
            return;
        }
    }
    puts("No");
}

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

    return 0;
}

F - Negative Traveling Salesman

解题思路:

\(f[s][i]:经过了s二进制表示的城市(数位中1为经过城市),最后到达城市i的最短权值\)

\(floyd\),然后状态压缩\(dp\)

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
const int N = 25;
ll d[N][N];
ll f[1ll << 20][25];
void solve()
{
    int n, m;
    cin >> n >> m;
    memset(d, 0x3f, sizeof d);
    memset(f, 0x3f, sizeof f);
    for (int i = 1; i <= m; i++)
    {
        ll a, b, c;
        cin >> a >> b >> c;
        d[a][b] = min(d[a][b], c);
    }
    for (int k = 1; k <= n; k++)
    {
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
            }
        }
    }
    for (int i = 1; i <= n; i++)
    {
        f[1 << (i - 1)][i] = 0;
    }
    for (int s = 0; s < (1 << n); s++)
    {
        for (int i = 1; i <= n; i++)
        {
            if (s >> (i - 1) & 1)
            {
                for (int j = 1; j <= n; j++)
                {
                    if ((s >> (j - 1) & 1) && j != i)
                    {
                        f[s][i] = min(f[s][i], f[s - (1 << (i - 1))][j] + d[j][i]);
                    }
                }
            }
        }
    }
    ll ans = 1e18;
    for (int i = 1; i <= n; i++)
    {
        ans = min(ans, (ll)f[(1ll << n) - 1][i]);
    }
    if (ans == 1e18)
    {
        puts("No");
        return;
    }
    cout << ans << endl;
}

int main()
{
    int t = 1;

    // cin >> t;

    while (t--)
    {
        solve();
    }

    return 0;
}
posted @ 2024-01-27 21:41  value0  阅读(34)  评论(0)    收藏  举报