QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#439168#8576. Symphony in c++ majorreal_sigma_team#TL 3ms3864kbC++234.8kb2024-06-11 17:26:482024-06-11 17:26:48

Judging History

你现在查看的是最新测评结果

  • [2024-06-11 17:26:48]
  • 评测
  • 测评结果:TL
  • 用时:3ms
  • 内存:3864kb
  • [2024-06-11 17:26:48]
  • 提交

answer

#pragma GCC optimize("O3,unroll-loops,inline")

#include <bits/stdc++.h>

using namespace std;

vector<pair<char, char>> can = {{' ', ' '},
                                {'d', 'o'},
                                {'r', 'e'},
                                {'m', 'i'},
                                {'f', 'a'},
                                {'s', 'o'},
                                {'l', 'a'},
                                {'t', 'i'}};

bool ok1(char c) {
    return c == ' ' || c == 'd' || c == 'r' || c == 'm' || c == 'f' || c == 's' || c == 'l' || c == 't';
}

bool ok2(char c) {
    return c == ' ' || c == 'o' || c == 'e' || c == 'i' || c == 'a';
}

struct node {
    map<pair<char, char>, pair<int, int>> dp;

    node() = default;

    node(char c) {
        dp[{c, c}] = {0, 1};
        dp[{' ', ' '}] = {1, 0};
    }
};

node operator+(node a, node b) {
    if (a.dp.empty())
        return b;
    if (b.dp.empty())
        return a;
    node c;
    for (auto note: can)
        for (auto [left, r1]: a.dp)
            for (auto [right, r2]: b.dp) {
                if (left.second == note.first && right.first == note.second) {
                    pair<int, int> now = {left.first, right.second};
                    if (r1.second == 1)
                        now.first = ' ';
                    if (r2.second == 1)
                        now.second = ' ';
                    if (c.dp.count(now))
                        c.dp[now] = min(c.dp[now], {r1.first + r2.first, r1.second + r2.second});
                    else
                        c.dp[now] = {r1.first + r2.first, r1.second + r2.second};
                }
                if (r1.second == 0) {
                    if (c.dp.count(right))
                        c.dp[right] = min(c.dp[right], {r1.first + r2.first, r1.second + r2.second});
                    else
                        c.dp[right] = {r1.first + r2.first, r1.second + r2.second};
                }
                if (r2.second == 0) {
                    if (c.dp.count(left))
                        c.dp[left] = min(c.dp[left], {r1.first + r2.first, r1.second + r2.second});
                    else
                        c.dp[left] = {r1.first + r2.first, r1.second + r2.second};
                }
            }
    vector<pair<pair<char, char>, pair<int, int>>> add;
    for (auto i: c.dp) {
        if (i.first.first != ' ')
            add.push_back({{' ',                i.first.second},
                           {i.second.first + 1, i.second.second - 1}});
        if (i.first.second != ' ')
            add.push_back({{i.first.first,      ' '},
                           {i.second.first + 1, i.second.second - 1}});
        add.push_back({{' ',                ' '},
                       {i.second.first + 1, i.second.first - 2}});
    }
    for (auto [i, j]: add)
        if (c.dp.count(i))
            c.dp[i] = min(c.dp[i], j);
        else
            c.dp[i] = j;
//    vector<pair<pair<char, char>, pair<int, int>>> del;
//    for (auto [i, j] : c.dp) {
//        if (!ok2(i.first) || !ok1(i.second))
//            del.push_back({i, j});
//    }
//    for (auto i : del)
//        c.dp.erase(i.first);
    return c;
}

struct segment_tree {
    vector<node> tree;
    int n;

    segment_tree(int n_) {
        n = n_;
        tree.resize(4 * n, node());
    }

    void upd(int v, int tl, int tr, int pos, char val) {
        if (tl == tr) {
            tree[v] = node(val);
            return;
        }
        int tm = (tl + tr) / 2;
        if (pos <= tm)
            upd(v * 2, tl, tm, pos, val);
        else
            upd(v * 2 + 1, tm + 1, tr, pos, val);
        tree[v] = tree[v * 2] + tree[v * 2 + 1];
    }

    node get(int v, int tl, int tr, int l, int r) {
        if (tr < l || r < tl)
            return node();
        if (l <= tl && tr <= r)
            return tree[v];
        int tm = (tl + tr) / 2;
        return get(v * 2, tl, tm, l, r) + get(v * 2 + 1, tm + 1, tr, l, r);
    }

    void upd(int pos, char val) {
        upd(1, 0, n - 1, pos, val);
    }

    int get(int l, int r) {
        return get(1, 0, n - 1, l, r).dp[{' ', ' '}].first;
    }
};

signed main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int n, q;
    cin >> n >> q;
    string s;
    cin >> s;
    segment_tree tr(n);
    for (int i = 0; i < n; ++i)
        tr.upd(i, s[i]);
    while (q--) {
        char t;
        cin >> t;
        if (t == '?') {
            int l, r;
            cin >> l >> r;
            --l, --r;
            cout << tr.get(l, r) << '\n';
        } else {
            int l, r;
            cin >> l >> r;
            --l, --r;
            string ns;
            cin >> ns;
            for (int i = l; i <= r; ++i)
                tr.upd(i, ns[i - l]);
        }
    }
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 3ms
memory: 3864kb

input:

8 10
eldorado
? 1 3
? 1 8
# 6 7 it
? 1 8
# 3 3 t
? 1 8
# 1 8 streamer
? 1 8
# 1 8 symphony
? 1 8

output:

3
4
6
6
6
6

result:

ok 6 numbers

Test #2:

score: -100
Time Limit Exceeded

input:

500000 300000
rfsraltzititrofomloldlaefikdemaddaafmimiioiuaueiaedifacmxamttiiitaaltiiireexeafsaaraedosotlaioootaiosizlifiioadhnxiofsasaflleaiisstaotdlliulilxatrpdaraaraaoiaeoooiumwuumarlifesroloistedoaaieolisaoatamsredorrfiifaaidfeassfioaiasmstomasallsftsrfaiiirteomaeiirefldmlaoaofrxlaeuilioirafotoa...

output:


result: