結果

問題 No.3122 Median of Medians of Division
ユーザー Takao Obi
提出日時 2025-04-19 15:05:35
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
TLE  
実行時間 -
コード長 2,842 bytes
コンパイル時間 3,647 ms
コンパイル使用メモリ 236,192 KB
実行使用メモリ 333,808 KB
最終ジャッジ日時 2025-04-19 15:05:47
合計ジャッジ時間 10,861 ms
ジャッジサーバーID
(参考情報)
judge3 / judge5
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample -- * 1
other TLE * 1 -- * 39
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using ll = long long;
using namespace __gnu_pbds;

// ordered multiset storing (value_id, position)
using OS = tree<pair<int,int>, null_type, less<pair<int,int>>, rb_tree_tag, tree_order_statistics_node_update>;

int N, Q;
vector<int> A;
vector<int> vals;
vector<OS> seg;

// Update segment tree: remove old pair (-1,-1) if oldv.first==-1 skip erase
void update_tree(int idx, int l, int r, int pos, const pair<int,int>& oldv, const pair<int,int>& newv) {
    if (oldv.first != -1) seg[idx].erase(oldv);
    seg[idx].insert(newv);
    if (l == r) return;
    int mid = (l + r) >> 1;
    if (pos <= mid) update_tree(idx<<1, l, mid, pos, oldv, newv);
    else             update_tree(idx<<1|1, mid+1, r, pos, oldv, newv);
}

// Query k-th smallest in [ql, qr]
int query_kth(int idx, int l, int r, int ql, int qr, int k) {
    if (l == r) return l;
    int mid = (l + r) >> 1;
    // count elements in left child within [ql,qr]
    auto &osl = seg[idx<<1];
    int cnt = osl.order_of_key({qr+1, -1}) - osl.order_of_key({ql, -1});
    if (cnt >= k) return query_kth(idx<<1, l, mid, ql, qr, k);
    else           return query_kth(idx<<1|1, mid+1, r, ql, qr, k - cnt);
}

struct Query { int t, i, x, l, r; };

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> N >> Q;
    A.resize(N);
    vals.reserve(N + Q);
    for (int i = 0; i < N; i++) {
        cin >> A[i];
        vals.push_back(A[i]);
    }
    vector<Query> qs(Q);
    for (int qi = 0; qi < Q; qi++) {
        cin >> qs[qi].t;
        if (qs[qi].t == 1) {
            cin >> qs[qi].i >> qs[qi].x;
            --qs[qi].i;
            vals.push_back(qs[qi].x);
        } else {
            cin >> qs[qi].l >> qs[qi].r;
            --qs[qi].l; --qs[qi].r;
        }
    }
    // compress
    sort(vals.begin(), vals.end());
    vals.erase(unique(vals.begin(), vals.end()), vals.end());
    int M = vals.size();
    auto getId = [&](int v){ return int(lower_bound(vals.begin(), vals.end(), v) - vals.begin()); };

    // build segment tree nodes
    seg.assign(4 * N, OS());
    // insert initial values
    for (int i = 0; i < N; i++) {
        int vid = getId(A[i]);
        update_tree(1, 0, N-1, i, {-1,-1}, {vid, i});
    }

    // process queries
    for (auto &q : qs) {
        if (q.t == 1) {
            int idx = q.i;
            int oldv = getId(A[idx]);
            int newv = getId(q.x);
            update_tree(1, 0, N-1, idx, {oldv, idx}, {newv, idx});
            A[idx] = q.x;
        } else {
            int l = q.l, r = q.r;
            int len = r - l + 1;
            int k = (len + 1) >> 1;
            int vid = query_kth(1, 0, N-1, l, r, k);
            cout << vals[vid] << '\n';
        }
    }
    return 0;
}
0