結果
問題 | No.1720 Division Permutation |
ユーザー | ei1333333 |
提出日時 | 2024-08-04 01:38:59 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 235 ms / 4,000 ms |
コード長 | 9,524 bytes |
コンパイル時間 | 5,143 ms |
コンパイル使用メモリ | 274,640 KB |
実行使用メモリ | 33,840 KB |
最終ジャッジ日時 | 2024-08-04 01:39:16 |
合計ジャッジ時間 | 15,867 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,816 KB |
testcase_01 | AC | 2 ms
6,812 KB |
testcase_02 | AC | 2 ms
6,944 KB |
testcase_03 | AC | 2 ms
6,944 KB |
testcase_04 | AC | 2 ms
6,940 KB |
testcase_05 | AC | 1 ms
6,944 KB |
testcase_06 | AC | 1 ms
6,944 KB |
testcase_07 | AC | 2 ms
6,940 KB |
testcase_08 | AC | 2 ms
6,940 KB |
testcase_09 | AC | 1 ms
6,940 KB |
testcase_10 | AC | 2 ms
6,940 KB |
testcase_11 | AC | 2 ms
6,944 KB |
testcase_12 | AC | 2 ms
6,940 KB |
testcase_13 | AC | 235 ms
33,712 KB |
testcase_14 | AC | 218 ms
33,840 KB |
testcase_15 | AC | 132 ms
21,500 KB |
testcase_16 | AC | 202 ms
32,992 KB |
testcase_17 | AC | 143 ms
25,984 KB |
testcase_18 | AC | 152 ms
31,544 KB |
testcase_19 | AC | 210 ms
31,396 KB |
testcase_20 | AC | 227 ms
31,396 KB |
testcase_21 | AC | 209 ms
31,272 KB |
testcase_22 | AC | 207 ms
31,140 KB |
testcase_23 | AC | 209 ms
31,200 KB |
testcase_24 | AC | 215 ms
31,144 KB |
testcase_25 | AC | 221 ms
31,140 KB |
testcase_26 | AC | 212 ms
31,268 KB |
testcase_27 | AC | 212 ms
31,268 KB |
testcase_28 | AC | 214 ms
31,164 KB |
testcase_29 | AC | 209 ms
31,012 KB |
testcase_30 | AC | 206 ms
31,012 KB |
testcase_31 | AC | 227 ms
31,400 KB |
testcase_32 | AC | 2 ms
6,940 KB |
testcase_33 | AC | 1 ms
6,940 KB |
testcase_34 | AC | 1 ms
6,940 KB |
testcase_35 | AC | 2 ms
6,940 KB |
testcase_36 | AC | 2 ms
6,940 KB |
testcase_37 | AC | 2 ms
6,940 KB |
testcase_38 | AC | 2 ms
6,944 KB |
testcase_39 | AC | 2 ms
6,940 KB |
testcase_40 | AC | 2 ms
6,944 KB |
testcase_41 | AC | 2 ms
6,940 KB |
testcase_42 | AC | 2 ms
6,940 KB |
testcase_43 | AC | 191 ms
28,520 KB |
testcase_44 | AC | 164 ms
26,744 KB |
testcase_45 | AC | 151 ms
25,220 KB |
testcase_46 | AC | 112 ms
18,596 KB |
testcase_47 | AC | 154 ms
25,236 KB |
testcase_48 | AC | 130 ms
19,616 KB |
testcase_49 | AC | 192 ms
28,936 KB |
testcase_50 | AC | 149 ms
24,644 KB |
testcase_51 | AC | 129 ms
19,444 KB |
testcase_52 | AC | 185 ms
27,776 KB |
testcase_53 | AC | 221 ms
31,780 KB |
testcase_54 | AC | 212 ms
33,840 KB |
testcase_55 | AC | 208 ms
31,396 KB |
testcase_56 | AC | 208 ms
31,272 KB |
testcase_57 | AC | 219 ms
33,840 KB |
testcase_58 | AC | 211 ms
31,392 KB |
testcase_59 | AC | 225 ms
31,140 KB |
testcase_60 | AC | 210 ms
33,840 KB |
testcase_61 | AC | 213 ms
31,648 KB |
testcase_62 | AC | 214 ms
31,780 KB |
ソースコード
#include <bits/stdc++.h> #if __has_include(<atcoder/all>) #include <atcoder/all> #endif using namespace std; using int64 = long long; const int64 infll = (1LL << 62) - 1; const int inf = (1 << 30) - 1; struct IoSetup { IoSetup() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(10); cerr << fixed << setprecision(10); } } iosetup; template< typename T1, typename T2 > ostream &operator<<(ostream &os, const pair< T1, T2 > &p) { os << p.first << " " << p.second; return os; } template< typename T1, typename T2 > istream &operator>>(istream &is, pair< T1, T2 > &p) { is >> p.first >> p.second; return is; } template< typename T > ostream &operator<<(ostream &os, const vector< T > &v) { for (int i = 0; i < (int) v.size(); i++) { os << v[i] << (i + 1 != v.size() ? " " : ""); } return os; } template< typename T > istream &operator>>(istream &is, vector< T > &v) { for (T &in: v) is >> in; return is; } template< typename T1, typename T2 > inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); } template< typename T1, typename T2 > inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); } template< typename T = int64 > vector< T > make_v(size_t a) { return vector< T >(a); } template< typename T, typename... Ts > auto make_v(size_t a, Ts... ts) { return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...)); } template< typename T, typename V > typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) { t = v; } template< typename T, typename V > typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) { for (auto &e: t) fill_v(e, v); } template< typename F > struct FixPoint: F { explicit FixPoint(F &&f): F(std::forward< F >(f)) {} template< typename... Args > decltype(auto) operator()(Args &&...args) const { return F::operator()(*this, std::forward< Args >(args)...); } }; template< typename F > inline decltype(auto) MFP(F &&f) { return FixPoint< F >{std::forward< F >(f)}; } template <typename ActedMonoid> struct LazySegmentTree { using S = typename ActedMonoid::S; using F = typename ActedMonoid::F; private: ActedMonoid m; int n{}, sz{}, height{}; vector<S> data; vector<F> lazy; inline void update(int k) { data[k] = m.op(data[2 * k + 0], data[2 * k + 1]); } inline void all_apply(int k, const F &x) { data[k] = m.mapping(data[k], x); if (k < sz) lazy[k] = m.composition(lazy[k], x); } inline void propagate(int k) { if (lazy[k] != m.id()) { all_apply(2 * k + 0, lazy[k]); all_apply(2 * k + 1, lazy[k]); lazy[k] = m.id(); } } public: LazySegmentTree() = default; explicit LazySegmentTree(ActedMonoid m, int n) : m(m), n(n) { sz = 1; height = 0; while (sz < n) sz <<= 1, height++; data.assign(2 * sz, m.e()); lazy.assign(2 * sz, m.id()); } explicit LazySegmentTree(ActedMonoid m, const vector<S> &v) : LazySegmentTree(m, v.size()) { build(v); } void build(const vector<S> &v) { assert(n == (int)v.size()); for (int k = 0; k < n; k++) data[k + sz] = v[k]; for (int k = sz - 1; k > 0; k--) update(k); } void set(int k, const S &x) { k += sz; for (int i = height; i > 0; i--) propagate(k >> i); data[k] = x; for (int i = 1; i <= height; i++) update(k >> i); } S get(int k) { k += sz; for (int i = height; i > 0; i--) propagate(k >> i); return data[k]; } S operator[](int k) { return get(k); } S prod(int l, int r) { if (l >= r) return m.e(); l += sz; r += sz; for (int i = height; i > 0; i--) { if (((l >> i) << i) != l) propagate(l >> i); if (((r >> i) << i) != r) propagate((r - 1) >> i); } S L = m.e(), R = m.e(); for (; l < r; l >>= 1, r >>= 1) { if (l & 1) L = m.op(L, data[l++]); if (r & 1) R = m.op(data[--r], R); } return m.op(L, R); } S all_prod() const { return data[1]; } void apply(int k, const F &f) { k += sz; for (int i = height; i > 0; i--) propagate(k >> i); data[k] = m.mapping(data[k], f); for (int i = 1; i <= height; i++) update(k >> i); } void apply(int l, int r, const F &f) { if (l >= r) return; l += sz; r += sz; for (int i = height; i > 0; i--) { if (((l >> i) << i) != l) propagate(l >> i); if (((r >> i) << i) != r) propagate((r - 1) >> i); } { int l2 = l, r2 = r; for (; l < r; l >>= 1, r >>= 1) { if (l & 1) all_apply(l++, f); if (r & 1) all_apply(--r, f); } l = l2, r = r2; } for (int i = 1; i <= height; i++) { if (((l >> i) << i) != l) update(l >> i); if (((r >> i) << i) != r) update((r - 1) >> i); } } template <typename C> int find_first(int l, const C &check) { if (l >= n) return n; l += sz; for (int i = height; i > 0; i--) propagate(l >> i); S sum = m.e(); do { while ((l & 1) == 0) l >>= 1; if (check(m.op(sum, data[l]))) { while (l < sz) { propagate(l); l <<= 1; auto nxt = m.op(sum, data[l]); if (not check(nxt)) { sum = nxt; l++; } } return l + 1 - sz; } sum = m.op(sum, data[l++]); } while ((l & -l) != l); return n; } template <typename C> int find_last(int r, const C &check) { if (r <= 0) return -1; r += sz; for (int i = height; i > 0; i--) propagate((r - 1) >> i); S sum = m.e(); do { r--; while (r > 1 and (r & 1)) r >>= 1; if (check(m.op(data[r], sum))) { while (r < sz) { propagate(r); r = (r << 1) + 1; auto nxt = m.op(data[r], sum); if (not check(nxt)) { sum = nxt; r--; } } return r - sz; } sum = m.op(data[r], sum); } while ((r & -r) != r); return -1; } }; template< typename T > struct RangeAddRangeMin { using S = T; using F = T; static constexpr S op(const S &a, const S &b) { return min(a, b); } static constexpr S e() { return numeric_limits<T>::max(); } static constexpr F mapping(const S &x, const F &f) { return x + f; } static constexpr F composition(const F &f, const F &g) { return f + g; } static constexpr F id() { return {0}; } }; struct PermutationTree { public: enum NodeType { JOIN_ASC, JOIN_DESC, LEAF, CUT }; struct Node { NodeType type; int l, r; // [l, r) int min_v, max_v; // [min_v, max_v) vector<Node *> ch; size_t size() const { return r - l; } bool is_join() const { return type == JOIN_ASC or type == JOIN_DESC; }; bool is_leaf() const { return type == LEAF; } bool is_cut() const { return type == CUT; } }; using NP = Node *; PermutationTree() = default; private: static void add_child(NP t, NP c) { t->ch.emplace_back(c); t->l = min(t->l, c->l); t->r = max(t->r, c->r); t->min_v = min(t->min_v, c->min_v); t->max_v = max(t->max_v, c->max_v); } public: static NP build(vector<int> &A) { int n = (int)A.size(); vector<int> desc{-1}; vector<int> asc{-1}; vector<NP> st; LazySegmentTree seg{RangeAddRangeMin< int >(), vector<int>(n)}; for (int i = 0; i < n; i++) { while (~desc.back() and A[i] > A[desc.back()]) { seg.apply(desc[desc.size() - 2] + 1, desc.back() + 1, A[i] - A[desc.back()]); desc.pop_back(); } while (~asc.back() and A[i] < A[asc.back()]) { seg.apply(asc[asc.size() - 2] + 1, asc.back() + 1, A[asc.back()] - A[i]); asc.pop_back(); } desc.emplace_back(i); asc.emplace_back(i); NP t = new Node{LEAF, i, i + 1, A[i], A[i] + 1, {}}; for (;;) { NodeType type = CUT; if (not st.empty()) { if (st.back()->max_v == t->min_v) { type = JOIN_ASC; } else if (t->max_v == st.back()->min_v) { type = JOIN_DESC; } } if (type != CUT) { NP r = st.back(); if (type != r->type) { r = new Node{type, r->l, r->r, r->min_v, r->max_v, {r}}; } add_child(r, t); st.pop_back(); t = r; } else if (seg.prod(0, i + 1 - (int)t->size()) == 0) { t = new Node{CUT, t->l, t->r, t->min_v, t->max_v, {t}}; do { add_child(t, st.back()); st.pop_back(); } while (t->max_v - t->min_v != t->size()); reverse(begin(t->ch), end(t->ch)); } else { break; } } st.emplace_back(t); seg.apply(0, i + 1, -1); } return st[0]; } }; using mint = atcoder::modint998244353; int main() { int N, K; cin >> N >> K; vector< int > A(N); cin >> A; for(auto &a: A) --a; using NP = PermutationTree::Node *; auto dp = make_v< mint >(K + 1, N + 1); dp[0][0] = 1; MFP([&](auto rec, NP r) -> void { if(r->is_cut() or r->is_leaf()) { for(int k = 0; k < K; k++) { dp[k + 1][r->r] += dp[k][r->l]; } } vector< mint > sum(K); for(auto &c: r->ch) { rec(c); if(r->is_join()) { for(int k = 0; k < K; k++) { dp[k + 1][c->r] += sum[k]; sum[k] += dp[k][c->l]; } } } })(PermutationTree::build(A)); for(int i = 1; i <= K; i++) { cout << dp[i][N].val() << "\n"; } }