結果
問題 | No.1720 Division Permutation |
ユーザー | 👑 rin204 |
提出日時 | 2024-05-06 14:58:32 |
言語 | C++23 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 313 ms / 4,000 ms |
コード長 | 14,607 bytes |
コンパイル時間 | 3,655 ms |
コンパイル使用メモリ | 266,540 KB |
実行使用メモリ | 32,664 KB |
最終ジャッジ日時 | 2024-05-06 14:58:50 |
合計ジャッジ時間 | 15,935 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 3 ms
5,376 KB |
testcase_05 | AC | 2 ms
5,376 KB |
testcase_06 | AC | 3 ms
5,376 KB |
testcase_07 | AC | 2 ms
5,376 KB |
testcase_08 | AC | 2 ms
5,376 KB |
testcase_09 | AC | 2 ms
5,376 KB |
testcase_10 | AC | 2 ms
5,376 KB |
testcase_11 | AC | 2 ms
5,376 KB |
testcase_12 | AC | 2 ms
5,376 KB |
testcase_13 | AC | 294 ms
32,080 KB |
testcase_14 | AC | 313 ms
32,336 KB |
testcase_15 | AC | 171 ms
21,256 KB |
testcase_16 | AC | 276 ms
31,132 KB |
testcase_17 | AC | 193 ms
22,560 KB |
testcase_18 | AC | 216 ms
32,200 KB |
testcase_19 | AC | 293 ms
32,660 KB |
testcase_20 | AC | 288 ms
32,664 KB |
testcase_21 | AC | 282 ms
32,400 KB |
testcase_22 | AC | 277 ms
32,532 KB |
testcase_23 | AC | 273 ms
32,528 KB |
testcase_24 | AC | 286 ms
32,664 KB |
testcase_25 | AC | 298 ms
32,400 KB |
testcase_26 | AC | 282 ms
32,404 KB |
testcase_27 | AC | 299 ms
32,656 KB |
testcase_28 | AC | 294 ms
32,528 KB |
testcase_29 | AC | 283 ms
32,528 KB |
testcase_30 | AC | 283 ms
32,656 KB |
testcase_31 | AC | 284 ms
32,660 KB |
testcase_32 | AC | 1 ms
5,376 KB |
testcase_33 | AC | 2 ms
5,376 KB |
testcase_34 | AC | 2 ms
5,376 KB |
testcase_35 | AC | 2 ms
5,376 KB |
testcase_36 | AC | 1 ms
5,376 KB |
testcase_37 | AC | 2 ms
5,376 KB |
testcase_38 | AC | 2 ms
5,376 KB |
testcase_39 | AC | 1 ms
5,376 KB |
testcase_40 | AC | 2 ms
5,376 KB |
testcase_41 | AC | 2 ms
5,376 KB |
testcase_42 | AC | 2 ms
5,376 KB |
testcase_43 | AC | 246 ms
28,116 KB |
testcase_44 | AC | 231 ms
26,200 KB |
testcase_45 | AC | 206 ms
24,072 KB |
testcase_46 | AC | 148 ms
19,236 KB |
testcase_47 | AC | 211 ms
24,760 KB |
testcase_48 | AC | 165 ms
20,376 KB |
testcase_49 | AC | 258 ms
29,184 KB |
testcase_50 | AC | 202 ms
23,820 KB |
testcase_51 | AC | 179 ms
20,424 KB |
testcase_52 | AC | 233 ms
26,596 KB |
testcase_53 | AC | 287 ms
32,376 KB |
testcase_54 | AC | 287 ms
32,088 KB |
testcase_55 | AC | 283 ms
32,224 KB |
testcase_56 | AC | 293 ms
32,300 KB |
testcase_57 | AC | 297 ms
32,088 KB |
testcase_58 | AC | 303 ms
32,252 KB |
testcase_59 | AC | 298 ms
32,200 KB |
testcase_60 | AC | 290 ms
32,084 KB |
testcase_61 | AC | 291 ms
32,408 KB |
testcase_62 | AC | 289 ms
32,224 KB |
ソースコード
#include <bits/stdc++.h> using namespace std; template <int MOD> struct Modint { int x; Modint() : x(0) {} Modint(int64_t y) { if (y >= 0) x = y % MOD; else x = (y % MOD + MOD) % MOD; } Modint &operator+=(const Modint &p) { x += p.x; if (x >= MOD) x -= MOD; return *this; } Modint &operator-=(const Modint &p) { x -= p.x; if (x < 0) x += MOD; return *this; } Modint &operator*=(const Modint &p) { x = int(1LL * x * p.x % MOD); return *this; } Modint &operator/=(const Modint &p) { *this *= p.inverse(); return *this; } Modint &operator%=(const Modint &p) { assert(p.x == 0); return *this; } Modint operator-() const { return Modint(-x); } Modint &operator++() { x++; if (x == MOD) x = 0; return *this; } Modint &operator--() { if (x == 0) x = MOD; x--; return *this; } Modint operator++(int) { Modint result = *this; ++*this; return result; } Modint operator--(int) { Modint result = *this; --*this; return result; } friend Modint operator+(const Modint &lhs, const Modint &rhs) { return Modint(lhs) += rhs; } friend Modint operator-(const Modint &lhs, const Modint &rhs) { return Modint(lhs) -= rhs; } friend Modint operator*(const Modint &lhs, const Modint &rhs) { return Modint(lhs) *= rhs; } friend Modint operator/(const Modint &lhs, const Modint &rhs) { return Modint(lhs) /= rhs; } friend Modint operator%(const Modint &lhs, const Modint &rhs) { assert(rhs.x == 0); return Modint(lhs); } bool operator==(const Modint &p) const { return x == p.x; } bool operator!=(const Modint &p) const { return x != p.x; } bool operator<(const Modint &rhs) const { return x < rhs.x; } bool operator<=(const Modint &rhs) const { return x <= rhs.x; } bool operator>(const Modint &rhs) const { return x > rhs.x; } bool operator>=(const Modint &rhs) const { return x >= rhs.x; } Modint inverse() const { int a = x, b = MOD, u = 1, v = 0, t; while (b > 0) { t = a / b; a -= t * b; u -= t * v; std::swap(a, b); std::swap(u, v); } return Modint(u); } Modint pow(int64_t k) const { Modint ret(1); Modint y(x); while (k > 0) { if (k & 1) ret *= y; y *= y; k >>= 1; } return ret; } friend std::ostream &operator<<(std::ostream &os, const Modint &p) { return os << p.x; } friend std::istream &operator>>(std::istream &is, Modint &p) { int64_t y; is >> y; p = Modint<MOD>(y); return (is); } static int get_mod() { return MOD; } }; struct Arbitrary_Modint { int x; static int MOD; static void set_mod(int mod) { MOD = mod; } Arbitrary_Modint() : x(0) {} Arbitrary_Modint(int64_t y) { if (y >= 0) x = y % MOD; else x = (y % MOD + MOD) % MOD; } Arbitrary_Modint &operator+=(const Arbitrary_Modint &p) { x += p.x; if (x >= MOD) x -= MOD; return *this; } Arbitrary_Modint &operator-=(const Arbitrary_Modint &p) { x -= p.x; if (x < 0) x += MOD; return *this; } Arbitrary_Modint &operator*=(const Arbitrary_Modint &p) { x = int(1LL * x * p.x % MOD); return *this; } Arbitrary_Modint &operator/=(const Arbitrary_Modint &p) { *this *= p.inverse(); return *this; } Arbitrary_Modint &operator%=(const Arbitrary_Modint &p) { assert(p.x == 0); return *this; } Arbitrary_Modint operator-() const { return Arbitrary_Modint(-x); } Arbitrary_Modint &operator++() { x++; if (x == MOD) x = 0; return *this; } Arbitrary_Modint &operator--() { if (x == 0) x = MOD; x--; return *this; } Arbitrary_Modint operator++(int) { Arbitrary_Modint result = *this; ++*this; return result; } Arbitrary_Modint operator--(int) { Arbitrary_Modint result = *this; --*this; return result; } friend Arbitrary_Modint operator+(const Arbitrary_Modint &lhs, const Arbitrary_Modint &rhs) { return Arbitrary_Modint(lhs) += rhs; } friend Arbitrary_Modint operator-(const Arbitrary_Modint &lhs, const Arbitrary_Modint &rhs) { return Arbitrary_Modint(lhs) -= rhs; } friend Arbitrary_Modint operator*(const Arbitrary_Modint &lhs, const Arbitrary_Modint &rhs) { return Arbitrary_Modint(lhs) *= rhs; } friend Arbitrary_Modint operator/(const Arbitrary_Modint &lhs, const Arbitrary_Modint &rhs) { return Arbitrary_Modint(lhs) /= rhs; } friend Arbitrary_Modint operator%(const Arbitrary_Modint &lhs, const Arbitrary_Modint &rhs) { assert(rhs.x == 0); return Arbitrary_Modint(lhs); } bool operator==(const Arbitrary_Modint &p) const { return x == p.x; } bool operator!=(const Arbitrary_Modint &p) const { return x != p.x; } bool operator<(const Arbitrary_Modint &rhs) { return x < rhs.x; } bool operator<=(const Arbitrary_Modint &rhs) { return x <= rhs.x; } bool operator>(const Arbitrary_Modint &rhs) { return x > rhs.x; } bool operator>=(const Arbitrary_Modint &rhs) { return x >= rhs.x; } Arbitrary_Modint inverse() const { int a = x, b = MOD, u = 1, v = 0, t; while (b > 0) { t = a / b; a -= t * b; u -= t * v; std::swap(a, b); std::swap(u, v); } return Arbitrary_Modint(u); } Arbitrary_Modint pow(int64_t k) const { Arbitrary_Modint ret(1); Arbitrary_Modint y(x); while (k > 0) { if (k & 1) ret *= y; y *= y; k >>= 1; } return ret; } friend std::ostream &operator<<(std::ostream &os, const Arbitrary_Modint &p) { return os << p.x; } friend std::istream &operator>>(std::istream &is, Arbitrary_Modint &p) { int64_t y; is >> y; p = Arbitrary_Modint(y); return (is); } static int get_mod() { return MOD; } }; int Arbitrary_Modint::MOD = 998244353; using modint9 = Modint<998244353>; using modint1 = Modint<1000000007>; using modint = Arbitrary_Modint; template <class S, S (*op)(S, S), S (*e)(), class F, S (*mapping)(F, S), F (*composition)(F, F), F (*id)()> struct lazy_segtree { public: explicit lazy_segtree(const std::vector<S> &v) : _n(int(v.size())) { size = 1; log = 0; while (size < _n) { log++; size <<= 1; } d = std::vector<S>(2 * size, e()); lz = std::vector<F>(size, id()); for (int i = 0; i < _n; i++) d[size + i] = v[i]; for (int i = size - 1; i >= 1; i--) update(i); } explicit lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {} S prod(int l, int r) { if (l == r) return e(); l += size; r += size; for (int i = log; i >= 1; i--) { if (((l >> i) << i) != l) push(l >> i); if (((r >> i) << i) != r) push((r - 1) >> i); } S sml = e(), smr = e(); while (l < r) { if (l & 1) sml = op(sml, d[l++]); if (r & 1) smr = op(d[--r], smr); l >>= 1; r >>= 1; } return op(sml, smr); } S get(int x) { return prod(x, x + 1); } S all_prod() { return d[1]; } void apply(int l, int r, F f) { if (l == r) return; l += size; r += size; for (int i = log; i >= 1; i--) { if (((l >> i) << i) != l) push(l >> i); if (((r >> i) << i) != r) push((r - 1) >> i); } { int l2 = l, r2 = r; while (l < r) { if (l & 1) all_apply(l++, f); if (r & 1) all_apply(--r, f); l >>= 1; r >>= 1; } l = l2; r = r2; } for (int i = 1; i <= log; i++) { if (((l >> i) << i) != l) update(l >> i); if (((r >> i) << i) != r) update((r - 1) >> i); } } private: int _n, size, log; std::vector<S> d; std::vector<F> lz; void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); } void all_apply(int k, F f) { d[k] = mapping(f, d[k]); if (k < size) lz[k] = composition(f, lz[k]); } void push(int k) { all_apply(2 * k, lz[k]); all_apply(2 * k + 1, lz[k]); lz[k] = id(); } }; namespace PerTreeRangeAddRangeMin { using S = int; S op(S l, S r) { return l < r ? l : r; } S e() { return 1 << 30; } using F = int; S mapping(F f, S x) { return f + x; } F composition(F f, F g) { return f + g; } F id() { return 0; } using SEG = lazy_segtree<S, op, e, F, mapping, composition, id>; } // namespace PerTreeRangeAddRangeMin struct PermutationTree { enum NodeType { JOIN_ASC, JOIN_DESC, CUT, LEAF, NONE, }; struct Node { NodeType tp; int l, r; int x_min, x_max; std::vector<int> child; int size() { return r - l; } }; int root; std::vector<int> P; std::vector<Node> nodes; PermutationTree() : root(-1) {} PermutationTree(const std::vector<int> &P) : root(-1), P(P) { assert(!P.empty()); build(); } private: void add_child(int par, int chi) { nodes[par].child.push_back(chi); nodes[par].l = std::min(nodes[par].l, nodes[chi].l); nodes[par].r = std::max(nodes[par].r, nodes[chi].r); nodes[par].x_min = std::min(nodes[par].x_min, nodes[chi].x_min); nodes[par].x_max = std::max(nodes[par].x_max, nodes[chi].x_max); } void build() { PerTreeRangeAddRangeMin::SEG seg((std::vector<int>(P.size()))); std::stack<int> hi, lo; hi.push(-1); lo.push(-1); std::stack<int> st; for (int i = 0; i < int(P.size()); i++) { while (hi.size() >= 2 and P[i] > P[hi.top()]) { auto hi_fi = hi.top(); hi.pop(); auto hi_se = hi.empty() ? -1 : hi.top(); seg.apply(hi_se + 1, hi_fi + 1, P[i] - P[hi_fi]); } hi.push(i); while (lo.size() >= 2 and P[i] < P[lo.top()]) { auto lo_fi = lo.top(); lo.pop(); auto lo_se = lo.empty() ? -1 : lo.top(); seg.apply(lo_se + 1, lo_fi + 1, P[lo_fi] - P[i]); } lo.push(i); int h = nodes.size(); nodes.push_back({NodeType::LEAF, i, i + 1, P[i], P[i], std::vector<int>()}); while (1) { NodeType join_tp = NodeType::NONE; if (!st.empty() and nodes[st.top()].x_max + 1 == nodes[h].x_min) { join_tp = NodeType::JOIN_ASC; } else if (!st.empty() and nodes[h].x_max + 1 == nodes[st.top()].x_min) { join_tp = NodeType::JOIN_DESC; } if (!st.empty() and join_tp != NodeType::NONE) { const Node &vtp = nodes[st.top()]; if (join_tp == vtp.tp) { add_child(st.top(), h); h = st.top(); st.pop(); } else { int j = st.top(); nodes.push_back( {join_tp, nodes[j].l, nodes[j].r, nodes[j].x_min, nodes[j].x_max, {j}}); st.pop(); add_child(nodes.size() - 1, h); h = nodes.size() - 1; } } else if (seg.prod(0, i + 1 - nodes[h].size()) == 0) { int l = nodes[h].l; int r = nodes[h].r; int x_max = nodes[h].x_max; int x_min = nodes[h].x_min; nodes.push_back({NodeType::CUT, l, r, x_min, x_max, {h}}); h = nodes.size() - 1; do { add_child(h, st.top()); st.pop(); } while (nodes[h].x_max - nodes[h].x_min + 1 != nodes[h].size()); std::reverse(nodes[h].child.begin(), nodes[h].child.end()); } else { break; } } st.push(h); seg.apply(0, i + 1, -1); } assert(st.size() == 1); root = st.top(); } }; using mint = modint9; void solve() { int n, k; cin >> n >> k; vector<int> P(n); for (int i = 0; i < n; i++) { cin >> P[i]; P[i]--; } PermutationTree pt(P); vector<vector<mint>> dp(n + 1, vector<mint>(k + 1, 0)); dp[0][0] = 1; auto dfs = [&](auto &&self, int pos) -> void { auto &u = pt.nodes[pos]; if (u.tp == PermutationTree::NodeType::LEAF or u.tp == PermutationTree::NodeType::CUT) { for (int i = 0; i < k; i++) { dp[u.r][i + 1] += dp[u.l][i]; } } vector<mint> add(k, 0); for (auto npos : u.child) { self(self, npos); auto &v = pt.nodes[npos]; if (u.tp == PermutationTree::NodeType::JOIN_ASC or u.tp == PermutationTree::NodeType::JOIN_DESC) { for (int i = 0; i < k; i++) { dp[v.r][i + 1] += add[i]; add[i] += dp[v.l][i]; } } } }; dfs(dfs, pt.root); for (int i = 1; i <= k; i++) { cout << dp[n][i] << endl; } } int main() { // cin.tie(0)->sync_with_stdio(0); int t; t = 1; // cin >> t; while (t--) solve(); return 0; }