QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#576104#9245. Bracket Sequenceucup-team3519TL 0ms3592kbC++206.7kb2024-09-19 18:27:082024-09-19 18:27:08

Judging History

This is the latest submission verdict.

  • [2024-09-19 18:27:08]
  • Judged
  • Verdict: TL
  • Time: 0ms
  • Memory: 3592kb
  • [2024-09-19 18:27:08]
  • Submitted

answer

#include <bits/stdc++.h>

template <int m>
struct ModInt {
private:
    int raw_;
    using mint = ModInt;
    using i64 = int64_t;

public:
    ModInt() : raw_(0) {}
    ModInt(const auto &v) : raw_(v % m) {}
    int value() const {
        return (raw_ + m) % m;
    }

    mint &operator+=(const mint &rhs) {
        raw_ = (raw_ + rhs.raw_) % m;
        return *this;
    }
    mint &operator-=(const mint &rhs) {
        raw_ = (raw_ - rhs.raw_) % m;
        return *this;
    }
    mint &operator*=(const mint &rhs) {
        raw_ = (i64)raw_ * rhs.raw_ % m;
        return *this;
    }
    mint &operator/=(const mint &rhs) {
        raw_ = (i64)raw_ * qpow(rhs.raw_, m - 2) % m;
        return *this;
    }

    friend mint operator+(const mint &lhs, const mint &rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint &lhs, const mint &rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint &lhs, const mint &rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint &lhs, const mint &rhs) {
        return mint(lhs) /= rhs;
    }

    static constexpr int mod() {
        return m;
    }

    static constexpr int qpow(int a, int b) {
        int res = 1;
        while (b) {
            if (b & 1) {
                res = (i64)res * a % m;
            }
            a = (i64)a * a % m, b >>= 1;
        }
        return res;
    }
};

using mint = ModInt<998244353>;
constexpr int K = 20;

struct DP {
    int n;
    std::array<std::array<std::array<mint, K + 1>, 2>, 2> a;
    std::array<std::array<mint, K + 1>, 2> l, r;
    std::array<mint, K + 1> res;
    friend DP operator*(const DP &lhs, const DP &rhs) {
        DP res;
        res.n = lhs.n + rhs.n;

        for (int k = 0; k <= K; ++k) {
            res.res[k] += lhs.res[k];
            res.res[k] += rhs.res[k];
            res.res[k] += lhs.l[0][k] * rhs.n;
            res.res[k] += lhs.n * rhs.r[0][k];
        }
        for (int mid = 0; mid < 2; ++mid) {
            for (int x = 0; x <= K; ++x) {
                for (int y = 0; x + y + mid <= K; ++y) {
                    res.res[x + y + mid] += lhs.l[mid][x] * rhs.r[mid][y];
                }
            }
        }

        for (int mid = 0; mid < 2; ++mid) {
            for (int f = 0; f < 2; ++f) {
                for (int x = 0; x <= K; ++x) {
                    for (int y = 0; x + y + mid <= K; ++y) {
                        res.l[f][x + y + mid] +=
                            lhs.l[mid][x] * rhs.a[mid][f][y];
                        res.r[f][x + y + mid] +=
                            lhs.a[f][mid][x] * rhs.r[mid][y];
                    }
                }
            }
        }
        for (int f = 0; f < 2; ++f) {
            for (int k = 0; k <= K; ++k) {
                res.l[f][k] += lhs.l[f][k];
                res.l[f][k] += rhs.l[f][k] + lhs.n * rhs.a[0][f][k];

                res.r[f][k] += rhs.r[f][k];
                res.r[f][k] += lhs.r[f][k] + lhs.a[f][0][k] * rhs.n;
            }
        }

        for (int left = 0; left < 2; ++left) {
            for (int right = 0; right < 2; ++right) {
                for (int k = 0; k <= K; ++k) {
                    res.a[left][right][k] += lhs.a[left][right][k];
                    res.a[left][right][k] += rhs.a[left][right][k];
                }
                for (int mid = 0; mid < 2; ++mid) {
                    for (int x = 0; x <= K; ++x) {
                        for (int y = 0; x + y + mid <= K; ++y) {
                            res.a[left][right][x + y + mid] +=
                                lhs.a[left][mid][x] * rhs.a[mid][right][y];
                        }
                    }
                }
            }
        }
        return res;
    }
};

int topbit(int x) {
    int res = 0;
    while (x > 1) {
        x >>= 1;
        ++res;
    }
    return res;
}

void monoid_product(const std::vector<DP> &vec,
                    const std::vector<std::pair<int, int>> &query, auto f) {
    const int n = vec.size();
    std::vector<std::vector<int>> buk(n);
    for (int id = 0; id < query.size(); ++id) {
        auto [l, r] = query[id];
        if (l == r) {
            continue;
        }
        int k = topbit(l ^ r);
        buk[r >> k << k].push_back(id);
    }

    std::vector<DP> dp(n);
    for (int mid = 1; mid < n; ++mid) {
        int min = mid, max = mid;
        for (int id : buk[mid]) {
            auto [l, r] = query[id];
            min = std::min(min, l);
            max = std::max(max, r);
        }
        dp[mid - 1] = vec[mid - 1];
        for (int i = mid - 2; i >= min; --i) {
            dp[i] = vec[i] * dp[i + 1];
        }
        dp[mid] = vec[mid];
        for (int i = mid + 1; i <= max; ++i) {
            dp[i] = dp[i - 1] * vec[i];
        }
        for (int id : buk[mid]) {
            auto [l, r] = query[id];
            f(dp[l], dp[r], id);
        }
    }
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, q;
    std::cin >> n >> q;

    std::string s;
    std::cin >> s;

    std::vector<std::pair<int, int>> query(q);
    std::vector<int> ops(q), ks(q);
    for (int i = 0; i < q; ++i) {
        int l, r;
        std::cin >> ops[i] >> l >> r >> ks[i];
        --l, --r;
        query[i] = {l, r};
    }

    std::vector<DP> vec(n);
    for (int i = 0; i < n; ++i) {
        vec[i].n = 1;
        auto &a = vec[i].a;
        auto &l = vec[i].l, &r = vec[i].r;
        if (s[i] == '(') {
            a[0][1][0] = 1;
            l[1][0] = 1;
        } else {
            a[1][0][0] = 1;
            r[1][0] = 1;
        }
    }

    std::vector<mint> ans(q);
    auto f = [&](const DP &L, const DP &R, int id) {
        const int k = ks[id];
        mint &res = ans[id];

        if (ops[id] == 1) {
            res += L.a[0][0][k];
            res += R.a[0][0][k];
            for (int i = 0; i <= k; ++i) {
                res += L.a[0][0][i] * R.a[0][0][k - i];
                if (i + 1 <= k) {
                    res += L.a[0][1][i] * R.a[1][0][k - i - 1];
                }
            }
        } else {
            res += L.res[k];
            res += R.res[k];
            res += L.l[0][k] * R.n;
            res += L.n * R.r[0][k];
            for (int mid = 0; mid < 2; ++mid) {
                for (int x = 0; x + mid <= k; ++x) {
                    res += L.l[mid][x] * R.r[mid][k - mid - x];
                }
            }
        }
    };
    monoid_product(vec, query, f);

    for (const auto &i : ans) {
        std::cout << i.value() << '\n';
    }
}

详细

Test #1:

score: 100
Accepted
time: 0ms
memory: 3592kb

input:

5 20
(()()
1 1 2 1
1 1 3 1
1 1 4 1
1 1 5 1
1 2 3 1
1 2 4 1
1 2 5 1
1 3 4 1
1 3 5 1
1 4 5 1
2 1 3 1
2 1 4 1
2 1 5 1
2 2 3 1
2 2 4 1
2 2 5 1
2 3 5 1
2 4 5 1
1 1 5 2
2 1 5 2

output:

0
2
2
5
1
1
3
0
1
1
3
6
16
1
2
7
2
1
2
3

result:

ok 20 lines

Test #2:

score: -100
Time Limit Exceeded

input:

100000 1000000
)())))))())()()()(())))()())))()))))())))))()(()()))()()))((()()))()))((())(())())()(()))))()))(()()()()()(())(()((()))()((()(()))()))()))()()))(())))()()(()(()())())((()((()((())()(()()))())(())())())))))))((())(((()(())())))(()(((())())))(((((((((()))()())())(()))(())()()()()((()())...

output:


result: