AtCoder Beginner Contest 342 A-G

A

void solve()
{
    string s, s1;
    cin >> s;
    s1 = s;
    sort(s1.begin(), s1.end());
    char ans;
    if (s1[0] == s1[1])
        ans = s1.back();
    else
        ans = s1[0];
    for (int i = 0; i < s.size(); i++)
        if (s[i] == ans)
        {
            cout << i + 1 << endl;
            return;
        }
}

B

void solve()
{
    int n;
    cin >> n;
    map<int, int> mp;
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        mp[x] = i;
    }
    int q;
    cin >> q;
    for (int i = 1; i <= q; i++)
    {
        int a, b;
        cin >> a >> b;
        cout << (mp[a] > mp[b] ? b : a) << endl;
    }
}

C

暴力合并即可

void solve()
{
    vector<vector<int>> a(100);
    int n, q;
    string s;
    cin >> n;

    cin >> s;
    for (int i = 0; i < s.size(); i++)
        a[(s[i] - 'a')].push_back(i);
    cin >> q;
    for (int i = 1; i <= q; i++)
    {
        char u, v;
        cin >> u >> v;
        int x = u - 'a', y = v - 'a';
        if (x == y)
            continue;
        if (a[x].empty())
            continue;
        else
        {
            if (a[y].size())
            {
                for (auto e : a[x])
                    a[y].push_back(e);
                a[x].clear();
            }
            else
                swap(a[x], a[y]);
        }
    }
    vector<char> ans(n + 1, '#');
    for (int i = 0; i < 26; i++)
    {
        for (auto p : a[i])
            ans[p] = char('a' + i);
    }
    for (int i = 0; i < n; i++)
        cout << ans[i];
}

D

答案只有以下几种情况:

假设0既不是平方数,也不是非平凡数

1.平方数*平方数

2.非平方数*非平方数

3.0*非零

4.非零*0

1.3.4可以直接计数,接下来考虑怎么算2对答案的贡献

考虑平方数的性质,每个质因子的指数都是偶数,所以两个非平方数相乘也要满足

记录一下非平方数中指数是奇数的数的乘积,这个乘积是唯一的,用map计数即可

void solve()
{
    auto getpr = [&](int n)
    {
        vector<bool> not_pr(n + 10, 0);
        for (int i = 2; i <= n; ++i)
        {
            if (!not_pr[i])
                pr.push_back(i);
            for (int p : pr)
            {
                if (i * p > n)
                    break;
                not_pr[i * p] = true;
                if (i % p == 0) // 说明i*p已经被一个更小的i判断过了
                    break;
            }
        }
    };
    getpr(450);
    ll n, cnt = 0, ans = 0, zero = 0;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        ll x;
        cin >> x;
        if (!x)
        {
            ans += i - 1;
            zero++;
            continue;
        }
        ans += zero;
        ll fac = 1;
        auto chk = [&]() -> void
        {
            for (auto p : pr)
            {
                if (p > x)
                    break;
                if (x % p == 0)
                {
                    ll num = 0;
                    while (x % p == 0)
                        x /= p, num++;
                    if (num & 1)
                        fac *= p;
                }
            }
            if (x > 1)
                fac *= x;
        };
        chk();
        ans += mp[fac];
        mp[fac]++;
    }
    cout << ans << endl;
}

E

建反图跑最短路

void solve()
{
    int n, m;
    cin >> n >> m;

    vector<vector<array<ll, 5>>> e(n + 1);
    for (int i = 1; i <= m; i++)
    {
        ll l, d, k, c, a, b;
        cin >> l >> d >> k >> c >> a >> b;
        e[b].push_back({l, d, k, c, a});
    }
    priority_queue<pll> pq;
    vector<ll> dis(n + 1, -1);
    vector<bool> vis(n + 1, 0);
    dis[n] = 2e18;
    pq.push({dis[n], n});
    while (pq.size())
    {
        auto [dist, u] = pq.top();
        pq.pop();
        if (vis[u])
            continue;
        vis[u] = 1;
        for (auto [l, d, k, c, a] : e[u])
        {
            ll lst = (dis[u] - l - c) / d;
            lst = min(lst, k - 1);
            if (l + lst * d > dis[a])
            {
                dis[a] = l + lst * d;
                pq.push({dis[a], a});
            }
        }
    }
    for (int i = 1; i < n; i++)
        if (dis[i] == -1)
            cout << "Unreachable" << endl;
        else
            cout << dis[i] << endl;
}

F

概率dp

f[i]表示点数为i是,采取最优策略的获胜概率

每个当前位置有两种情况:

掷色子,\(f[i]=\sum_{j=i+1}^{i+d}f[j]\)

不掷骰子,\(loss(i)\)表示点数为i时,获胜的概率

这个dp明显要倒着处理

#include <bits/stdc++.h>
#define endl '\n'
#define x first
#define y second
#define ls(x) (a[x].l)
#define rs(x) (a[x].r)
#define sum(x) a[x].sum
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef double db;
const ll mod = 1e9 + 7;
const int N = 1e6 + 100, M = 2;
random_device rd;
mt19937_64 gen(rd());
struct BIT
{
    int n;
    vector<db> a;
    BIT(int _n) : n(_n), a(n + 10) {}
    int lb(int x) { return x & -x; }
    void add(int x, db y)
    {
        x++;
        for (; x <= n; x += lb(x))
            a[x] += y;
    }
    void modify(int l, int r, db x)
    {
        add(l, x);
        add(r + 1, -x);
    }
    db query(int x)
    {
        x++;
        db res = 0.;
        for (; x; x ^= lb(x))
            res += a[x];
        return res;
    }
};
void solve()
{
    int n, l, d;
    cin >> n >> l >> d;
    vector<db> g(2 * n + 10, 0.), f(2 * n + 10, 0.);
    auto lose = [&](int x) -> db
    {
        if (x > n)
            return 0.;
        db res = 1 - g[n];
        if (x > l)
            res += g[x - 1];
        return res;
    };
    auto cal_g = [&]() -> void
    {
        BIT bit(2 * n);
        bit.modify(0, 0, 1.0);
        for (int i = 0; i <= 2 * n; i++)
        {
            g[i] = bit.query(i);
            if (i < l)
            {
                bit.modify(i + 1, i + d, g[i] / d);
                g[i] = 0;
            }
        }
        for (int i = 1; i <= 2 * n; i++)
            g[i] += g[i - 1];
    };
    auto cal_f = [&]() -> void
    {
        db sum = 0;
        for (int i = 2 * n; i >= 0; i--)
        {
            if (i > n)
                f[i] = 0;
            else
            {
                f[i] = max(sum / d, lose(i));
            }
            sum += f[i];
            if (i + d <= 2 * n)
                sum -= f[i + d];
        }
    };
    cal_g();
    cal_f();
    cout << f[0] << endl;
}
int main()
{
    cout << setprecision(10);
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int _ = 1;
    // cin >> _;
    while (_--)
        solve();
    return 0;
}

G

建一棵以mulitset作为节点的线段树

操作1就是对节点打标记(不下传)

操作2就是删除标记(暴力删)

操作3从叶子往上走,不断取max即可

struct segtree
{
    int n;
    vector<multiset<int>> a;
    vector<int> leaf;
    segtree(int _n) : n(_n * 4 + 10), a(n + 1), leaf(_n + 10) {}
    void build(int id, int l, int r)
    {
        if (l == r)
            leaf[l] = id;
        else
        {
            int mid = l + r >> 1;
            build(id * 2, l, mid);
            build(id * 2 + 1, mid + 1, r);
        }
    }
    void modify(int id, int l, int r, int ql, int qr, int t)
    {
        if (r < ql || l > qr)
            return;
        if (l >= ql && r <= qr)
        {
            if (t > 0)
                a[id].insert(t);
            else
                a[id].extract(-t);
            return;
        }
        int mid = l + r >> 1;
        if (ql <= mid)
            modify(id * 2, l, mid, ql, qr, t);
        if (qr > mid)
            modify(id * 2 + 1, mid + 1, r, ql, qr, t);
    }
    ll query(int x)
    {
        int id = leaf[x];
        int ans = 0;
        while (id > 0)
        {
            if (a[id].size())
                ans = max(ans, *a[id].rbegin());
            id /= 2;
        }
        return ans;
    }
};
void solve()
{
    int n, q;
    cin >> n;
    vector<ll> a(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    cin >> q;
    segtree seg(n);
    seg.build(1, 1, n);
    int opt, l, r, x;
    vector<array<int, 3>> op(q + 1);
    for (int i = 1; i <= q; i++)
    {
        cin >> opt;
        if (opt == 1)
        {
            cin >> l >> r >> x;
            seg.modify(1, 1, n, l, r, x);
            op[i] = {l, r, x};
        }
        else if (opt == 2)
        {
            cin >> x;
            auto [l, r, t] = op[x];
            seg.modify(1, 1, n, l, r, -t);
        }
        else
        {
            cin >> x;
            cout << max(a[x], seg.query(x)) << endl;
        }
    }
}

进一步优化时间,可以将mulitset优化成一个带修堆

struct segtree
{
    struct heap
    {
        priority_queue<int> p, q;
        void push(int x)
        {
            p.push(x);
        }
        int top()
        {
            while (p.size() && q.size() && p.top() == q.top())
                p.pop(), q.pop();
            if (p.size())
                return p.top();
            return -1;
        }
        void del(int x)
        {
            q.push(x);
        }
    };
    int n;
    vector<heap> a;
    vector<int> leaf;
    segtree(int _n) : n(_n * 4 + 10), a(n + 1), leaf(_n + 10) {}
    void build(int id, int l, int r)
    {
        if (l == r)
            leaf[l] = id;
        else
        {
            int mid = l + r >> 1;
            build(id * 2, l, mid);
            build(id * 2 + 1, mid + 1, r);
        }
    }
    void modify(int id, int l, int r, int ql, int qr, int t)
    {
        if (r < ql || l > qr)
            return;
        if (l >= ql && r <= qr)
        {
            if (t > 0)
                a[id].push(t);
            else
                a[id].del(-t);
            return;
        }
        int mid = l + r >> 1;
        if (ql <= mid)
            modify(id * 2, l, mid, ql, qr, t);
        if (qr > mid)
            modify(id * 2 + 1, mid + 1, r, ql, qr, t);
    }
    ll query(int x)
    {
        int id = leaf[x];
        int ans = 0;
        while (id > 0)
        {
            ans = max(ans, a[id].top());
            id /= 2;
        }
        return ans;
    }
};
void solve()
{
    int n, q;
    cin >> n;
    vector<ll> a(n + 1);
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    cin >> q;
    segtree seg(n);
    seg.build(1, 1, n);
    int opt, l, r, x;
    vector<array<int, 3>> op(q + 1);
    for (int i = 1; i <= q; i++)
    {
        cin >> opt;
        if (opt == 1)
        {
            cin >> l >> r >> x;
            seg.modify(1, 1, n, l, r, x);
            op[i] = {l, r, x};
        }
        else if (opt == 2)
        {
            cin >> x;
            auto [l, r, t] = op[x];
            seg.modify(1, 1, n, l, r, -t);
        }
        else
        {
            cin >> x;
            cout << max(a[x], seg.query(x)) << endl;
        }
    }
}
posted @ 2024-02-28 22:31  0x3ea  阅读(1)  评论(0编辑  收藏  举报