結果
問題 |
No.3122 Median of Medians of Division
|
ユーザー |
|
提出日時 | 2025-04-20 06:35:12 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 7,004 bytes |
コンパイル時間 | 2,942 ms |
コンパイル使用メモリ | 217,804 KB |
実行使用メモリ | 96,076 KB |
最終ジャッジ日時 | 2025-04-20 06:35:24 |
合計ジャッジ時間 | 11,185 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | -- * 1 |
other | TLE * 1 -- * 39 |
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; // --- Fenwick Tree (1-indexed internally) --- struct Fenwick { int n; vector<int> t; Fenwick(int _n=0): n(_n), t(n+1,0) {} void init(int _n){ n = _n; t.assign(n+1, 0); } // add v at index i (0-based) void update(int i, int v){ for(++i; i <= n; i += i & -i) t[i] += v; } // sum [0..i] (0-based) int query(int i) const { int s = 0; for(++i; i > 0; i -= i & -i) s += t[i]; return s; } // sum [l..r] int query(int l, int r) const { if(l > r) return 0; return query(r) - (l? query(l-1) : 0); } }; // --- イベント構造体 --- struct Upd { int time; // イベント発生時刻:0 が「初期値」、1..Q がクエリ番号 int pos; // 更新位置 (A: [0..N-1], B: [0..N-2]) int c; // 圧縮後の値 int delta; // +1 or -1 }; struct Query { int time; // クエリ発生時刻(1..Q) int l, r; // range [l..r] int len; // = r-l+1 int id; // 元のクエリ順序(1..Q) int ans; // 探索後の圧縮値 }; // 再帰的 Parallel Binary Search // qids: まだ答えが確定していないクエリのインデックス集合 // valL..valR: この区間で二分探索中。最終的に [val, val+1) になる void solve(int valL, int valR, vector<int>& qids, const vector<Upd>& Aev, const vector<Upd>& Bev, vector<Query>& Qs, Fenwick& bitA, Fenwick& bitB) { if(qids.empty()) return; if(valL + 1 == valR){ // この閾値に確定 for(int qi : qids) Qs[qi].ans = valL; return; } int mid = (valL + valR) >> 1; // クエリ時間順に並べる vector<int> order = qids; sort(order.begin(), order.end(), [&](int a, int b){ return Qs[a].time < Qs[b].time; }); vector<int> leftQ, rightQ; vector<int> appliedA, appliedB; int pA = 0, pB = 0; // BIT はこの recursion の開始時点ですべて 0 であることを仮定 for(int qi : order){ int qt = Qs[qi].time; // A-events を時刻 qt まで流し込む while(pA < (int)Aev.size() && Aev[pA].time <= qt){ if(Aev[pA].c >= mid){ bitA.update(Aev[pA].pos, Aev[pA].delta); appliedA.push_back(pA); } ++pA; } // B-events を時刻 qt まで流し込む while(pB < (int)Bev.size() && Bev[pB].time <= qt){ if(Bev[pB].c < mid){ bitB.update(Bev[pB].pos, Bev[pB].delta); appliedB.push_back(pB); } ++pB; } // 条件判定 int ge = bitA.query(Qs[qi].l, Qs[qi].r); int lt_pairs = (Qs[qi].l < Qs[qi].r ? bitB.query(Qs[qi].l, Qs[qi].r - 1) : 0); if(2LL * ge + lt_pairs > Qs[qi].len) rightQ.push_back(qi); else leftQ.push_back(qi); } // ロールバック for(int idx : appliedA){ bitA.update(Aev[idx].pos, -Aev[idx].delta); } for(int idx : appliedB){ bitB.update(Bev[idx].pos, -Bev[idx].delta); } // 再帰 solve(valL, mid, leftQ, Aev, Bev, Qs, bitA, bitB); solve(mid, valR, rightQ, Aev, Bev, Qs, bitA, bitB); } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N, Q; cin >> N >> Q; vector<ll> A(N); for(int i = 0; i < N; i++) cin >> A[i]; struct InQ { int type, i, l, r; ll x; }; vector<InQ> in(Q+1); // 先読みして座標圧縮のための候補を集める vector<vector<ll>> posA(N); for(int i = 0; i < N; i++) posA[i].push_back(A[i]); for(int qi = 1; qi <= Q; qi++){ cin >> in[qi].type; if(in[qi].type == 1){ cin >> in[qi].i >> in[qi].x; --in[qi].i; posA[in[qi].i].push_back(in[qi].x); } else { cin >> in[qi].l >> in[qi].r; --in[qi].l; --in[qi].r; } } // 全体圧縮 vector<ll> all; all.reserve(N + Q); for(int i = 0; i < N; i++){ auto &v = posA[i]; sort(v.begin(), v.end()); v.erase(unique(v.begin(), v.end()), v.end()); for(ll x : v) all.push_back(x); } sort(all.begin(), all.end()); all.erase(unique(all.begin(), all.end()), all.end()); int MA = all.size(); // 初期 Ac, Bc を計算 vector<int> Ac(N), Bc(max(0, N-1)); for(int i = 0; i < N; i++){ Ac[i] = int(lower_bound(all.begin(), all.end(), A[i]) - all.begin()); } for(int i = 0; i + 1 < N; i++){ Bc[i] = max(Ac[i], Ac[i+1]); } // イベント生成 vector<Upd> Aev, Bev; Aev.reserve(2*(N + Q)); Bev.reserve(2*(max(0,N-1) + Q)); // time=0: 初期値を add for(int i = 0; i < N; i++){ Aev.push_back({0, i, Ac[i], +1}); } for(int i = 0; i + 1 < N; i++){ Bev.push_back({0, i, Bc[i], +1}); } // queries list vector<Query> Qs; Qs.reserve(Q); // カレント配列 vector<int> curA = Ac, curB = Bc; for(int qi = 1; qi <= Q; qi++){ if(in[qi].type == 1){ int i = in[qi].i; int oldc = curA[i]; int newc = int(lower_bound(all.begin(), all.end(), in[qi].x) - all.begin()); // A のイベント Aev.push_back({qi, i, oldc, -1}); Aev.push_back({qi, i, newc, +1}); curA[i] = newc; // B のイベント (両隣) if(i > 0){ int p = i-1; int ob = curB[p]; int nb = max(curA[p], curA[p+1]); Bev.push_back({qi, p, ob, -1}); Bev.push_back({qi, p, nb, +1}); curB[p] = nb; } if(i+1 < N){ int p = i; int ob = curB[p]; int nb = max(curA[p], curA[p+1]); Bev.push_back({qi, p, ob, -1}); Bev.push_back({qi, p, nb, +1}); curB[p] = nb; } } else { // クエリを保存 Qs.push_back({ qi, in[qi].l, in[qi].r, in[qi].r - in[qi].l + 1, qi, /* id= time */ -1 }); } } // Fenwick 準備 Fenwick bitA(N), bitB(max(0, N-1)); // qids 初期化 vector<int> qids(Qs.size()); iota(qids.begin(), qids.end(), 0); // 再帰実行 solve(0, MA, qids, Aev, Bev, Qs, bitA, bitB); // 出力:時刻順に並んでいる Qs を使い、全体入力を走査して type2 のみ出力 // Qs[i].ans は「圧縮後の index」 // all[Qs[i].ans] が実際の値 for(auto &q : Qs){ cout << all[q.ans] << "\n"; } return 0; }