AtCoder Beginner Contest 341 A-G

A

void solve()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cout << "10";
    cout << "1" << endl;
}

B

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

C

暴力检查每个点

void solve()
{
    int n, m, k, ans = 0;
    cin >> n >> m >> k;
    vector<vector<char>> a(n + 1, vector<char>(m + 1));
    string s;
    cin >> s;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            cin >> a[i][j];
    auto chk = [&](int x, int y) -> bool
    {
        for (auto i : s)
        {
            if (i == 'L')
                y--;
            else if (i == 'R')
                y++;
            else if (i == 'U')
                x--;
            else
                x++;
            if (x < 1 || x > n || y < 1 || y > m || a[x][y] == '#')
                return false;
        }
        return true;
    };
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            if (a[i][j] == '.')
                ans += chk(i, j);
    cout << ans << endl;
}

D

二分答案,check时容斥一下即可

void solve()
{
    ll n, m, k;
    cin >> n >> m >> k;
    ll l = 1, r = 2e18, g = n / __gcd(n, m) * m;
    auto check = [&](ll x) -> bool
    {
        ll num = x / n + x / m - 2 * (x / g);
        return num >= k;
    };
    while (l < r)
    {
        ll mid = l + r >> 1;
        if (check(mid))
            r = mid;
        else
            l = mid + 1;
    }
    cout << l << endl;
}

E

发现每次反转对答案的影响只有\(l-,l\)\(r,r+1\),用树状数组维护答案,线段树维护原数组

struct node
{
    ll t, val, sz;
};
struct segtree
{
    int n;
    vector<node> a;
    segtree(int _n) : n(_n * 4 + 10), a(n + 1) {}
    void update(int id) { a[id].val = (a[id * 2].val + a[id * 2 + 1].val) % 2; }
    void settag(int id, ll t)
    {
        a[id].val = (a[id].val + t * (a[id].sz)) % 2;
        a[id].t = (a[id].t + t) % 2;
    }
    void pushdown(int id)
    {
        if (a[id].t)
        {
            settag(id * 2, a[id].t);
            settag(id * 2 + 1, a[id].t);
            a[id].t = 0;
        }
    }
    void build(int id, int l, int r, vector<int> &arr)
    {
        a[id].t = 0;
        a[id].sz = r - l + 1;
        if (l == r)
            a[id].val = arr[l];
        else
        {
            int mid = l + r >> 1;
            build(id * 2, l, mid, arr);
            build(id * 2 + 1, mid + 1, r, arr);
            update(id);
        }
    }
    void modify(int id, int l, int r, int ql, int qr, ll t)
    {
        if (l == ql && r == qr)
        {
            settag(id, t);
            return;
        }
        int mid = l + r >> 1;
        pushdown(id);
        if (qr <= mid)
            modify(id * 2, l, mid, ql, qr, t);
        else if (ql > mid)
            modify(id * 2 + 1, mid + 1, r, ql, qr, t);
        else
        {
            modify(id * 2, l, mid, ql, mid, t);
            modify(id * 2 + 1, mid + 1, r, mid + 1, qr, t);
        }
        update(id);
    }
    ll query(int id, int l, int r, int ql, int qr)
    {
        if (l == ql && r == qr)
            return a[id].val;
        int mid = l + r >> 1;
        pushdown(id);
        if (qr <= mid)
            return query(id * 2, l, mid, ql, qr);
        else if (ql > mid)
            return query(id * 2 + 1, mid + 1, r, ql, qr);
        else
        {
            return (query(id * 2, l, mid, ql, mid) + query(id * 2 + 1, mid + 1, r, mid + 1, qr)) % 2;
        }
    }
};
struct BIT
{
    int n;
    vector<ll> a;
    BIT(int _n) : n(_n), a(n + 1) {}
    int lb(int x) { return x & -x; }
    void build(int n, vector<int> &s)
    {
        for (int i = 1; i <= n; i++)
        {
            a[i] += s[i];
            int fa = i + lb(i);
            if (fa <= n)
                a[fa] += a[i];
        }
    }
    void add(int x, ll y)
    {
        for (; x <= n; x += lb(x))
            a[x] += y;
    }
    ll query(int x)
    {
        ll res = 0;
        for (; x; x ^= lb(x))
            res += a[x];
        return res;
    }
    int search(ll s) // 第一个小于等于s的位置
    {
        int pos = 0;
        for (int j = 20; j >= 0; j--)
            if (pos + (1 << j) <= n && a[pos + (1 << j)] <= s)
            {
                pos += (1 << j);
                s -= a[pos];
            }
        return pos;
    }
};
void solve()
{
    int n, q;
    string s;
    cin >> n >> q >> s;
    s = '#' + s;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++)
        a[i] = s[i] - '0';
    BIT bit(n);
    segtree seg(n);
    seg.build(1, 1, n, a);
    for (int i = 2; i <= n; i++)
        if (a[i] == a[i - 1])
            bit.add(i - 1, 1), bit.add(i, 1);
    int opt, l, r;
    for (int i = 1; i <= q; i++)
    {
        cin >> opt >> l >> r;
        if (opt == 1)
        {
            seg.modify(1, 1, n, l, r, 1);
            if (l > 1)
            {
                int fi = seg.query(1, 1, n, l - 1, l - 1);
                int se = seg.query(1, 1, n, l, l);
                if (fi != se)
                    bit.add(l - 1, -1), bit.add(l, -1);
                else
                    bit.add(l - 1, 1), bit.add(l, 1);
            }
            if (r < n)
            {
                int fi = seg.query(1, 1, n, r, r);
                int se = seg.query(1, 1, n, r + 1, r + 1);
                if (fi != se)
                    bit.add(r, -1), bit.add(r + 1, -1);
                else
                    bit.add(r, 1), bit.add(r + 1, 1);
            }
        }
        else
        {
            if (r - l > 1)
            {
                int chk = bit.query(r - 1) - bit.query(l);
                cout << (chk ? "No" : "Yes") << endl;
            }
            else
            {
                if (l == r)
                    cout << "Yes" << endl;
                else
                {
                    cout << (seg.query(1, 1, n, l, l) != seg.query(1, 1, n, r, r) ? "Yes" : "No") << endl;
                }
            }
        }
    }
}

F

发现点只会从w大的到w小的,这样原图就变成了一个DAG,在这个图上对每个点跑一边01背包即可

void solve()
{
    int n, m;
    cin >> n >> m;
    vector<vector<int>> e(n + 1);
    vector<ll> a(n + 1), v(n + 1), d(n + 1, 0);
    vector<ll> f(n + 1, 0), dp(N, 0);
    vector<pii> edge(m);
    for (auto &[u, v] : edge)
        cin >> u >> v;
    for (int i = 1; i <= n; i++)
        cin >> v[i];
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    for (auto [x, y] : edge)
    {
        if (v[x] > v[y])
            e[x].push_back(y), d[y]++;
        if (v[x] < v[y])
            e[y].push_back(x), d[x]++;
    }
    queue<int> q;
    vector<int> ord;
    for (int i = 1; i <= n; i++)
        if (!d[i])
            q.push(i);
    while (q.size())
    {
        auto t = q.front();
        ord.push_back(t);
        q.pop();
        for (auto to : e[t])
            if (--d[to] == 0)
                q.push(to);
    }
    reverse(ord.begin(), ord.end());
    for (auto u : ord)
    {
        for (int i = 0; i <= v[u]; i++)
            dp[i] = 0;
        dp[0] = 1;
        for (auto to : e[u])
            for (int i = v[u] - 1; i >= v[to]; i--)
                dp[i] = max(dp[i], dp[i - v[to]] + f[to]);
        for (int i = 0; i < v[u]; i++)
            f[u] = max(f[u], dp[i]);
    }

    ll ans = 0;
    for (int i = 1; i <= n; i++)
        ans += f[i] * a[i];
    cout << ans << endl;
}

G

设s为a的前缀和,那么有:

$ ave=\frac{s[r]-s[k]}{r-k+1} $

发现这个式子的数学含义表示斜率,也就是说,要求出一个r,使得斜率最大

将数组反转,题目转化为:

$ ave=\frac{s[k]-s[r]}{k-r+1} $

用单调栈维护每个位置

只要当前i与q[r]的斜率小于等于i与q[r-1]的斜率,那么就可以删除r(上凸壳)

void solve()
{
    int n;
    cin >> n;
    vector<ll> a(n + 1, 0), s(n + 1, 0);
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    reverse(a.begin() + 1, a.end());
    for (int i = 1; i <= n; i++)
        s[i] = s[i - 1] + a[i];
    vector<int> q(n + 10, 0);
    int r = -1;
    q[++r] = 0;
    vector<double> ans;
    for (int i = 1; i <= n; i++)
    {
        while (r > 0 && (s[i] - s[q[r]]) * (q[r] - q[r - 1]) <= (s[q[r]] - s[q[r - 1]]) * (i - q[r]))
            r--;
        ans.push_back(1.0 * (s[i] - s[q[r]]) / (i - q[r]));
        q[++r] = i;
    }
    reverse(ans.begin(), ans.end());
    for (auto i : ans)
        cout << i << endl;
}
posted @ 2024-02-18 16:51  0x3ea  阅读(1)  评论(0编辑  收藏  举报