結果
問題 | No.2950 Max Min Product |
ユーザー | zawakasu |
提出日時 | 2024-10-28 13:15:36 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 1,802 ms / 3,000 ms |
コード長 | 5,698 bytes |
コンパイル時間 | 1,533 ms |
コンパイル使用メモリ | 92,276 KB |
実行使用メモリ | 31,076 KB |
最終ジャッジ日時 | 2024-10-28 13:16:37 |
合計ジャッジ時間 | 59,594 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,820 KB |
testcase_01 | AC | 2 ms
6,816 KB |
testcase_02 | AC | 2 ms
6,816 KB |
testcase_03 | AC | 1,296 ms
22,048 KB |
testcase_04 | AC | 1,345 ms
23,964 KB |
testcase_05 | AC | 1,342 ms
22,764 KB |
testcase_06 | AC | 1,692 ms
30,644 KB |
testcase_07 | AC | 1,704 ms
30,640 KB |
testcase_08 | AC | 1,693 ms
30,700 KB |
testcase_09 | AC | 927 ms
17,244 KB |
testcase_10 | AC | 1,632 ms
27,104 KB |
testcase_11 | AC | 1,351 ms
23,896 KB |
testcase_12 | AC | 1,690 ms
30,676 KB |
testcase_13 | AC | 1,714 ms
30,752 KB |
testcase_14 | AC | 1,685 ms
30,664 KB |
testcase_15 | AC | 1,802 ms
28,916 KB |
testcase_16 | AC | 1,233 ms
21,852 KB |
testcase_17 | AC | 1,392 ms
23,712 KB |
testcase_18 | AC | 1,703 ms
30,640 KB |
testcase_19 | AC | 1,680 ms
30,688 KB |
testcase_20 | AC | 1,676 ms
30,600 KB |
testcase_21 | AC | 1,082 ms
19,780 KB |
testcase_22 | AC | 1,280 ms
24,248 KB |
testcase_23 | AC | 906 ms
17,728 KB |
testcase_24 | AC | 1,695 ms
30,944 KB |
testcase_25 | AC | 1,698 ms
30,948 KB |
testcase_26 | AC | 1,694 ms
31,076 KB |
testcase_27 | AC | 1,221 ms
21,872 KB |
testcase_28 | AC | 1,785 ms
29,308 KB |
testcase_29 | AC | 1,289 ms
22,716 KB |
testcase_30 | AC | 1,791 ms
30,580 KB |
testcase_31 | AC | 1,745 ms
30,696 KB |
testcase_32 | AC | 1,748 ms
30,692 KB |
testcase_33 | AC | 1,326 ms
23,360 KB |
testcase_34 | AC | 841 ms
16,924 KB |
testcase_35 | AC | 1,257 ms
22,800 KB |
testcase_36 | AC | 1,734 ms
30,552 KB |
testcase_37 | AC | 1,713 ms
30,460 KB |
testcase_38 | AC | 1,760 ms
30,576 KB |
testcase_39 | AC | 2 ms
6,816 KB |
ソースコード
#include <iostream> #include <vector> #include <utility> #include <optional> #include <cassert> #include <stack> const long long MOD{998244353}; long long norm(long long v) { return ((v % MOD) + MOD) % MOD; } long long add(long long L, long long R) { return (norm(L) + norm(R)) % MOD; } long long mult(long long L, long long R) { return (norm(L) * norm(R)) % MOD; } struct VD { long long max_sum{}, min_sum{}, prod_sum{}; int len{}; VD() = default; VD(long long mx, long long mn, long long pr, int l) : max_sum{mx}, min_sum{mn}, prod_sum{pr}, len{l} {} }; struct VM { using T = VD; static T identity() { return VD{}; } static T operation(T L, T R) { L.max_sum = add(L.max_sum, R.max_sum); L.min_sum = add(L.min_sum, R.min_sum); L.prod_sum = add(L.prod_sum, R.prod_sum); L.len += R.len; return L; } }; struct OM { using T = std::pair<std::optional<int>, std::optional<int>>; static T identity() { return T{ std::nullopt, std::nullopt }; } static T operation(T L, T R) { if (R.first) L.first = R.first; if (R.second) L.second = R.second; return L; } }; VM::T mapping(VM::T v, OM::T o) { if (o.first and o.second) { v.max_sum = mult(*o.first, v.len); v.min_sum = mult(*o.second, v.len); v.prod_sum = mult(*o.first, mult(*o.second, v.len)); } else if (o.first) { v.max_sum = mult(*o.first, v.len); v.prod_sum = mult(*o.first, v.min_sum); } else if (o.second) { v.min_sum = mult(*o.second, v.len); v.prod_sum = mult(*o.second, v.max_sum); } return v; } struct LazySegmentTree { using V = VM::T; using O = OM::T; static int parent(int v) { return v >>= 1; } static int left(int v) { return v << 1; } static int right(int v) { return v << 1 | 1; } static int depth(int v) { return 31 - __builtin_clz(v); } static int trailingZeros(int v) { return __builtin_ctz(v); } struct Node { V v{VM::identity()}; O o{OM::identity()}; }; int n{}; std::vector<Node> dat; static V action(const Node& node) { return mapping(node.v, node.o); } void propagate(int v) { dat[left(v)].o = OM::operation(dat[left(v)].o, dat[v].o); dat[right(v)].o = OM::operation(dat[right(v)].o, dat[v].o); dat[v].o = OM::identity(); } void propagateAncestor(int v) { int dep{depth(v)}; int zeros{trailingZeros(v)}; for (int d{dep} ; d != zeros ; d--) { propagate(v >> d); } } void recalc(int v) { dat[v].v = VM::operation(action(dat[left(v)]), action(dat[right(v)])); } void recalcAncestor(int v) { v >>= trailingZeros(v); for (v = parent(v) ; v ; v = parent(v)) { recalc(v); } } LazySegmentTree() = default; LazySegmentTree(const std::vector<V>& A) : n{(int)A.size()}, dat(A.size() << 1) { assert(A.size()); for (int i{} ; i < n ; i++) dat[i + n].v = A[i]; for (int i{n} ; --i ; ) { dat[i].v = VM::operation(dat[left(i)].v, dat[right(i)].v); } } int size() const { return n; } void operation(int L, int R, const O& o) { assert(0 <= L and L <= R and R <= n); L += size(); R += size(); propagateAncestor(L); propagateAncestor(R); for (int l{L}, r{R} ; l < r ; l = parent(l), r = parent(r)) { if (l & 1) { dat[l].o = OM::operation(dat[l].o, o); l++; } if (r & 1) { r--; dat[r].o = OM::operation(dat[r].o, o); } } recalcAncestor(L); recalcAncestor(R); } V product(int L, int R) { assert(0 <= L and L <= R and R <= n); L += size(); R += size(); propagateAncestor(L); propagateAncestor(R); recalcAncestor(L); recalcAncestor(R); V l{VM::identity()}, r{VM::identity()}; for ( ; L < R ; L = parent(L), R = parent(R)) { if (L & 1) { l = VM::operation(l, action(dat[L])); L++; } if (R & 1) { R--; r = VM::operation(action(dat[R]), r); } } return VM::operation(l, r); } }; int main() { std::cin.tie(nullptr)->sync_with_stdio(false); int N; std::cin >> N; std::vector<int> A(N); std::vector<VM::T> init(N); for (int i{} ; i < N ; i++) { int a; std::cin >> a; A[i] = a; init[i] = VM::T{a, a, (long long)a * a, 1}; } std::vector<int> prevmax(N, -1), prevmin(N, -1); { std::stack<int> stack; for (int i{} ; i < N ; i++) { while (stack.size() and A[stack.top()] < A[i]) stack.pop(); prevmax[i] = stack.size() ? stack.top() : -1; stack.push(i); } } { std::stack<int> stack; for (int i{} ; i < N ; i++) { while (stack.size() and A[stack.top()] > A[i]) stack.pop(); prevmin[i] = stack.size() ? stack.top() : -1; stack.push(i); } } LazySegmentTree seg{init}; long long ans{}; for (int i{} ; i < N ; i++) { seg.operation(prevmax[i] + 1, i, OM::T{ A[i], std::nullopt }); seg.operation(prevmin[i] + 1, i, OM::T{ std::nullopt, A[i] }); ans = add(ans, seg.product(0, i + 1).prod_sum); } std::cout << ans << '\n'; }