結果
問題 |
No.3122 Median of Medians of Division
|
ユーザー |
![]() |
提出日時 | 2025-04-20 11:59:10 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 403 ms / 2,000 ms |
コード長 | 5,577 bytes |
コンパイル時間 | 5,051 ms |
コンパイル使用メモリ | 287,560 KB |
実行使用メモリ | 17,460 KB |
最終ジャッジ日時 | 2025-04-20 11:59:31 |
合計ジャッジ時間 | 19,925 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 |
other | AC * 40 |
ソースコード
#include <bits/stdc++.h> using namespace std; // Segment Tree with half-open intervals [l, r): // - point update: set A[pos] = value // - range query: retrieve the maximum and second maximum in A[l..r) struct Node { int mx1, mx2; Node(int a = INT_MIN, int b = INT_MIN) : mx1(a), mx2(b) {} }; class SegTree { private: int n; vector<Node> st; // Merge two child nodes into parent Node merge(const Node &L, const Node &R) { Node res; if (L.mx1 >= R.mx1) { res.mx1 = L.mx1; res.mx2 = max(L.mx2, R.mx1); } else { res.mx1 = R.mx1; res.mx2 = max(R.mx2, L.mx1); } return res; } // build node p covering [l, r) void build(int p, int l, int r, const vector<int> &A) { if (r - l == 1) { st[p] = Node(A[l], INT_MIN); return; } int m = (l + r) >> 1; build(p<<1, l, m, A); build(p<<1|1, m, r, A); st[p] = merge(st[p<<1], st[p<<1|1]); } // update position idx to val in node p covering [l, r) void update(int p, int l, int r, int idx, int val) { if (r - l == 1) { st[p] = Node(val, INT_MIN); return; } int m = (l + r) >> 1; if (idx < m) update(p<<1, l, m, idx, val); else update(p<<1|1, m, r, idx, val); st[p] = merge(st[p<<1], st[p<<1|1]); } // query on [ql, qr) in node p covering [l, r) Node query(int p, int l, int r, int ql, int qr) { if (qr <= l || r <= ql) return Node(); if (ql <= l && r <= qr) return st[p]; int m = (l + r) >> 1; Node L = query(p<<1, l, m, ql, qr); Node R = query(p<<1|1, m, r, ql, qr); return merge(L, R); } public: // Initialize with array A (0-based) SegTree(const vector<int> &A) { n = A.size(); st.assign(4*n, Node()); build(1, 0, n, A); } // Point update: A[pos] = val void update(int pos, int val) { if (pos < 0 || pos >= n) return; update(1, 0, n, pos, val); } // Range query [l, r): returns Node with mx1, mx2 Node query(int l, int r) { if (l < 0) l = 0; if (r > n) r = n; if (l >= r) return Node(); return query(1, 0, n, l, r); } }; // 2) Segment Tree for minimum on even and odd indices on half-open intervals [l, r) struct NodeMin { int min_even, min_odd; NodeMin(int me = INT_MAX, int mo = INT_MAX) : min_even(me), min_odd(mo) {} }; class SegTreeMinParity { private: int n; vector<NodeMin> st; NodeMin merge(const NodeMin &L, const NodeMin &R) const { return NodeMin( min(L.min_even, R.min_even), min(L.min_odd, R.min_odd) ); } void build(int p, int l, int r, const vector<int> &A) { if (r - l == 1) { int me = (l % 2 == 0 ? A[l] : INT_MAX); int mo = (l % 2 == 1 ? A[l] : INT_MAX); st[p] = NodeMin(me, mo); return; } int m = (l + r) >> 1; build(p<<1, l, m, A); build(p<<1|1, m, r, A); st[p] = merge(st[p<<1], st[p<<1|1]); } void update(int p, int l, int r, int idx, int val) { if (r - l == 1) { int me = (l % 2 == 0 ? val : INT_MAX); int mo = (l % 2 == 1 ? val : INT_MAX); st[p] = NodeMin(me, mo); return; } int m = (l + r) >> 1; if (idx < m) update(p<<1, l, m, idx, val); else update(p<<1|1, m, r, idx, val); st[p] = merge(st[p<<1], st[p<<1|1]); } NodeMin query(int p, int l, int r, int ql, int qr) const { if (qr <= l || r <= ql) return NodeMin(); if (ql <= l && r <= qr) return st[p]; int m = (l + r) >> 1; NodeMin L = query(p<<1, l, m, ql, qr); NodeMin R = query(p<<1|1, m, r, ql, qr); return merge(L, R); } public: SegTreeMinParity(const vector<int> &A) { n = A.size(); st.assign(4*n, NodeMin()); build(1, 0, n, A); } void update(int pos, int val) { if (pos < 0 || pos >= n) return; update(1, 0, n, pos, val); } NodeMin query(int l, int r) const { if (l < 0) l = 0; if (r > n) r = n; if (l >= r) return NodeMin(); return query(1, 0, n, l, r); } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N, Q; cin >> N >> Q; vector<int> A(N); for (int i = 0; i < N; i++) cin >> A[i]; vector<int> B(N-1); for (int i = 0; i < N-1; i++) { B[i] = min(A[i], A[i+1]); } SegTree st(B); SegTreeMinParity stMin(A); while (Q--) { int type; cin >> type; if (type == 1) { int idx, x; cin >> idx >> x; idx--; A[idx] = x; if (idx > 0) { B[idx-1] = min(A[idx], A[idx-1]); st.update(idx-1, B[idx-1]); } if (idx < N-1) { B[idx] = min(A[idx], A[idx+1]); st.update(idx, B[idx]); } stMin.update(idx, A[idx]); } else if (type == 2) { int l, r; cin >> l >> r; l--; int ans = 0; Node res = st.query(l, r-1); ans = max(ans, min(A[l], A[r-1])); ans = max(ans, min(res.mx1, max(A[l], A[r-1]))); ans = max(ans, res.mx2); cout << ans << endl; } } return 0; }