Toyota Programming Contest 2024#2(AtCoder Beginner Contest 341)

Toyota Programming Contest 2024#2(AtCoder Beginner Contest 341)

A - Print 341

代码:

#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;
using piii = pair<ll, pair<ll, ll>>;

void solve()
{
    int n;
    cin >> n;
    int cur = 1;
    for (int i = 1; i <= 2 * n + 1; i++)
    {
        cout << cur;
        cur ^= 1;
    }
}

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

B - Foreign Exchange

代码:

#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;
using piii = pair<ll, pair<ll, ll>>;

void solve()
{
    ll n;
    cin >> n;
    vector<ll> a(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    vector<ll> s(n + 1), t(n + 1);
    for (int i = 1; i < n; i++)
    {
        cin >> s[i] >> t[i];
        ll k = a[i] / s[i];
        a[i + 1] += k * t[i];
    }
    cout << a[n] << endl;
}

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

C - Takahashi Gets Lost

代码:

#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;
using piii = pair<ll, pair<ll, ll>>;

void solve()
{
    int n, m, l;
    cin >> n >> m >> l;
    string s;
    cin >> s;
    vector<string> g(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> g[i];
        g[i] = ' ' + g[i];
    }
    auto bfs = [&](int a, int b) -> bool
    {
        for (auto c : s)
        {
            if (c == 'L')
            {
                b--;
            }
            else if (c == 'R')
            {
                b++;
            }
            else if (c == 'U')
            {
                a--;
            }
            else
            {
                a++;
            }
            if (g[a][b] != '.' || a < 1 || b < 1 || a > n || b > m)
            {
                return false;
            }
        }
        return true;
    };
    int cnt = 0;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            if (g[i][j] == '.')
            {
                if (bfs(i, j))
                {
                    cnt++;
                }
            }
        }
    }
    cout << cnt << endl;
}

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

D - Only one of two

解题思路:

假设答案为\(x\)

那么\(x\)\(a的倍数 + b的倍数 - ab的倍数= k\)。如果\(x\)变大,\(a的倍数 + b的倍数 - ab的倍数 \geq k\),反之,小于等于。

代码:

#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;
using piii = pair<ll, pair<ll, ll>>;

ll gcd(ll a, ll b)
{
    return b ? gcd(b, a % b) : a;
}

ll lcm(ll a, ll b)
{
    return a * b / gcd(a, b);
}

void solve()
{
    ll a, b, k;
    cin >> a >> b >> k;
    ll l = -1;
    ll r = 1e18;
    auto check = [&](ll mid)
    {
        ll c1 = mid / a;
        ll c2 = mid / b;
        ll c3 = mid / lcm(a, b);
        return (c1 + c2 - 2 * c3 >= k);
    };
    while (l + 1 < r)
    {
        ll mid = l + r >> 1;
        if (check(mid))
        {
            r = mid;
        }
        else
        {
            l = mid;
        }
    }
    cout << r << endl;
}

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

E - Alternating String

解题思路:

维护区间端点,区间修改,区间查询,可用线段树。

代码:

#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;
using piii = pair<ll, pair<ll, ll>>;
const int N = 5e5 + 10;
bool tr[N * 4];
int lc[N * 4];
int rc[N * 4];
int laz[N * 4];
int n, q;
string s;
void pushup(int u)
{
    lc[u] = lc[u << 1];
    rc[u] = rc[u << 1 | 1];
    if (rc[u << 1] == lc[u << 1 | 1])
    {
        tr[u] = false;
    }
    else
    {
        tr[u] = true;
    }
    if (tr[u << 1] == false || tr[u << 1 | 1] == false)
    {
        tr[u] = false;
    }
}

void pushdown(int u, int l, int r)
{
    if (laz[u])
    {
        lc[u << 1] ^= laz[u];
        rc[u << 1] ^= laz[u];
        lc[u << 1 | 1] ^= laz[u];
        rc[u << 1 | 1] ^= laz[u];
        laz[u << 1] ^= laz[u];
        laz[u << 1 | 1] ^= laz[u];
        laz[u] = 0;
    }
}

void build(int u, int l, int r)
{
    if (l == r)
    {
        tr[u] = true;
        rc[u] = lc[u] = s[l] - '0';
        laz[u] = 0;
        return;
    }
    int mid = l + r >> 1;
    build(u << 1, l, mid);
    build(u << 1 | 1, mid + 1, r);
    pushup(u);
}

void modify(int u, int l, int r, int nl, int nr)
{
    if (l >= nl && r <= nr)
    {
        lc[u] ^= 1;
        rc[u] ^= 1;
        laz[u] ^= 1;
        return;
    }
    pushdown(u, l, r);
    int mid = l + r >> 1;
    if (nl <= mid)
    {
        modify(u << 1, l, mid, nl, nr);
    }
    if (nr > mid)
    {
        modify(u << 1 | 1, mid + 1, r, nl, nr);
    }
    pushup(u);
}

array<int, 3> query(int u, int l, int r, int nl, int nr)
{
    if (l >= nl && r <= nr)
    {
        return {lc[u], rc[u], tr[u]};
    }
    pushdown(u, l, r);
    int mid = l + r >> 1;
    if (nr <= mid)
    {
        return query(u << 1, l, mid, nl, nr);
    }
    if (nl > mid)
    {
        return query(u << 1 | 1, mid + 1, r, nl, nr);
    }
    auto lson = query(u << 1, l, mid, nl, nr);
    auto rson = query(u << 1 | 1, mid + 1, r, nl, nr);
    array<int, 3> res;
    if (lson[1] == rson[0])
    {
        res[2] = false;
    }
    else
    {
        res[2] = true;
    }
    if (lson[2] == 0 || rson[2] == 0)
    {
        res[2] = false;
    }
    res[0] = lson[0];
    res[1] = rson[1];
    return res;
}



void solve()
{

    cin >> n >> q;
    cin >> s;
    s = ' ' + s;
    build(1, 1, n);
    while (q--)
    {
        int c, l, r;
        cin >> c >> l >> r;
        if (c == 1)
        {
            modify(1, 1, n, l, r);
        }
        else
        {
            auto res = query(1, 1, n, l, r);
            if (res[2] == 0)
            {
                puts("No");
            }
            else
            {
                puts("Yes");
            }
        }
    }
}

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

F - Breakdown

解题思路:

棋子只能从大权值点走向小权值点,所以图是\(DAG\)

\(dp[u][w]:点u周围结点权值和为w时,1个棋子的最大操作步数。\)

\(f[u]:点u一个棋子的最大操作步数。\)

对结点按权值升序排序。从小权值结点开始计算\(1\)个棋子的最大步数。对每个结点做一次\(01\)背包。

代码:

#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;
using piii = pair<ll, pair<ll, ll>>;
const int inf = 1 << 30;
void solve()
{
    int n, m;
    cin >> n >> m;
    vector<vector<int>> e(n + 1, vector<int>());
    for (int i = 1; i <= m; i++)
    {
        int a, b;
        cin >> a >> b;
        e[a].push_back(b);
        e[b].push_back(a);
    }
    vector<int> a(n + 1), w(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> w[i];
        a[i] = i;
    }
    auto cmp = [&](int x, int y) -> bool
    {
        return w[x] < w[y];
    };
    sort(a.begin() + 1, a.end(), cmp);
    vector<vector<ll>> dp(n + 1, vector<ll>(5010, 1));
    vector<ll> f(n + 1, 1);
    for (int i = 1; i <= n; i++)
    {
        int u = a[i];
        for (auto v : e[u])
        {
            if (w[v] >= w[u])
            {
                continue;
            }
            for (int j = w[u] - 1; j >= 0; j--)
            {
                if (w[v] <= j)
                {
                    dp[u][j] = max(dp[u][j], dp[u][j - w[v]] + f[v]);
                    f[u] = max(f[u], dp[u][j]);
                }
            }
        }
    }
    ll ans = 0;
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        ans += f[i] * x;
    }
    cout << ans << endl;
}

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

G - Highest Ratio

解题思路:

\(pre_i:前缀和数组。\)

\[\frac{pre_r - pre_{k - 1}}{r - k + 1} \]

我们将数组倒序,方便维护。

\[\frac{pre_i - pre_{j}}{i - j},(i > j) \]

\((i,pre_i)\)看作二维坐标上的一个点,不难发现我们要求最大斜率。

\(i和pre_i都是升序\),比较板子的斜率优化\(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;
using piii = pair<ll, pair<ll, ll>>;

void solve()
{
    int n;
    cin >> n;
    vector<double> a(n + 1);
    for (int i = n; i; i--)
    {
        cin >> a[i];
    }
    for (int i = 1; i <= n; i++)
    {
        a[i] += a[i - 1];
    }
    vector<int> q(n + 10);
    int hh = 0;
    int tt = 0;
    q[0] = 0;
    vector<double> ans;
    for (int i = 1; i <= n; i++)
    {
        while (hh < tt && (a[i] - a[q[tt]]) * (i - q[tt - 1]) <= (a[i] - a[q[tt - 1]]) * (i - q[tt]))
        {
            tt--;
        }
        int j = q[tt];
        ans.push_back((a[i] - a[j]) / (i - j));
        q[++tt] = i;
    }
    reverse(ans.begin(), ans.end());
    for (auto x : ans)
    {
        printf("%.10lf\n", x);
    }
}

int main()
{
    int t = 1;
    // cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}
posted @ 2024-02-20 23:32  value0  阅读(41)  评论(0)    收藏  举报