結果
| 問題 |
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;
}