結果

問題 No.3122 Median of Medians of Division
ユーザー Naru820
提出日時 2025-05-21 16:22:40
言語 C++23
(gcc 13.3.0 + boost 1.87.0)
結果
TLE  
実行時間 -
コード長 9,201 bytes
コンパイル時間 2,115 ms
コンパイル使用メモリ 117,616 KB
実行使用メモリ 60,160 KB
最終ジャッジ日時 2025-05-21 16:22:56
合計ジャッジ時間 14,663 ms
ジャッジサーバーID
(参考情報)
judge2 / judge1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample -- * 1
other TLE * 1 -- * 39
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <set>

using namespace std;

// Type definitions
using ll = long long;

// Structure for segment tree node
struct SegInfo {
    bool first_val_is_one;
    bool last_val_is_one;
    int ones_count;
    int transitions_1_to_0;
    bool is_empty;

    SegInfo() : first_val_is_one(false), last_val_is_one(false), ones_count(0), transitions_1_to_0(0), is_empty(true) {}
};

// Global segment tree and array (for simplicity in check function)
vector<ll> g_A_arr; // Global array A
vector<SegInfo> g_tree;
int g_N_seg; // Size of array for segment tree

// Merge function for segment tree nodes
SegInfo merge(const SegInfo& left, const SegInfo& right) {
    if (left.is_empty) return right;
    if (right.is_empty) return left;

    SegInfo res;
    res.is_empty = false;
    res.ones_count = left.ones_count + right.ones_count;
    res.first_val_is_one = left.first_val_is_one;
    res.last_val_is_one = right.last_val_is_one;
    res.transitions_1_to_0 = left.transitions_1_to_0 + right.transitions_1_to_0;
    if (left.last_val_is_one && !right.first_val_is_one) {
        res.transitions_1_to_0++;
    }
    return res;
}

// Build leaf node for segment tree
void build_leaf_seg_tree(int node_idx, int arr_idx, ll threshold_X) {
    if (arr_idx >= g_A_arr.size()) { // Should not happen if arr_idx is valid
        g_tree[node_idx].is_empty = true;
        return;
    }
    g_tree[node_idx].is_empty = false;
    bool is_one = (g_A_arr[arr_idx] >= threshold_X);
    g_tree[node_idx].ones_count = is_one ? 1 : 0;
    g_tree[node_idx].first_val_is_one = is_one;
    g_tree[node_idx].last_val_is_one = is_one;
    g_tree[node_idx].transitions_1_to_0 = 0;
}

// Build segment tree for a specific threshold X
void build_seg_tree(int node_idx, int l_arr, int r_arr, ll threshold_X) {
    if (l_arr == r_arr) {
        build_leaf_seg_tree(node_idx, l_arr, threshold_X);
    } else {
        int mid = l_arr + (r_arr - l_arr) / 2;
        build_seg_tree(2 * node_idx, l_arr, mid, threshold_X);
        build_seg_tree(2 * node_idx + 1, mid + 1, r_arr, threshold_X);
        g_tree[node_idx] = merge(g_tree[2 * node_idx], g_tree[2 * node_idx + 1]);
    }
}

// Query segment tree
SegInfo query_seg_tree(int node_idx, int l_arr, int r_arr, int q_l, int q_r) {
    if (q_l <= l_arr && r_arr <= q_r) {
        return g_tree[node_idx];
    }
    int mid = l_arr + (r_arr - l_arr) / 2;
    SegInfo res_left, res_right;
    if (q_l <= mid) {
        res_left = query_seg_tree(2 * node_idx, l_arr, mid, q_l, q_r);
    }
    if (q_r > mid) {
        res_right = query_seg_tree(2 * node_idx + 1, mid + 1, r_arr, q_l, q_r);
    }
    return merge(res_left, res_right);
}

// Check function for binary search
bool check(ll X_candidate, int l_query, int r_query, const vector<ll>& current_A_state) {
    // Use g_A_arr for the check, by copying current_A_state to it
    g_A_arr = current_A_state; // This copy is an O(N) operation.
                               // For faster parallel BS, g_A_arr itself would be updated.
                               // Here, for simple BS per query, this is fine conceptually.

    if (g_N_seg > 0) build_seg_tree(1, 0, g_N_seg - 1, X_candidate); else g_tree[1].is_empty = true;


    SegInfo range_info;
    if (l_query <= r_query && g_N_seg > 0) {
         range_info = query_seg_tree(1, 0, g_N_seg - 1, l_query, r_query);
    } else { 
        return false; // Empty query range or empty main array cannot satisfy condition normally
    }
   
    if (range_info.is_empty) return false; // Should not happen if l_query <= r_query

    int n1 = range_info.ones_count;
    int n0_seg = 0;
    if (!range_info.first_val_is_one) { 
        n0_seg = 1;
    }
    n0_seg += range_info.transitions_1_to_0;
    
    return n1 > n0_seg;
}


struct Query {
    int type;
    int p1, p2; 
    ll val_x; 
    int original_idx_for_ans; // For type 2 queries to map back to answers array
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int Q_count;
    cin >> g_N_seg >> Q_count;

    vector<ll> initial_A(g_N_seg);
    set<ll> distinct_coords_set;
    distinct_coords_set.insert(0); // A potential smallest answer if all elements are negative (not in this problem)
                                   // Or simply a baseline. The problem states 1 <= A_i.
                                   // So, smallest possible answer is 1, or smallest element.
                                   // A value smaller than all elements can be a sentinel for "no X works".

    for (int i = 0; i < g_N_seg; ++i) {
        cin >> initial_A[i];
        distinct_coords_set.insert(initial_A[i]);
    }

    vector<Query> queries(Q_count);
    vector<int> type2_original_indices; 
    for (int i = 0; i < Q_count; ++i) {
        cin >> queries[i].type;
        if (queries[i].type == 1) {
            cin >> queries[i].p1 >> queries[i].val_x;
            queries[i].p1--; // 0-indexed
            distinct_coords_set.insert(queries[i].val_x);
        } else {
            cin >> queries[i].p1 >> queries[i].p2;
            queries[i].p1--; 
            queries[i].p2--; 
            queries[i].original_idx_for_ans = type2_original_indices.size();
            type2_original_indices.push_back(i);
        }
    }

    vector<ll> distinct_coords(distinct_coords_set.begin(), distinct_coords_set.end());
    if (distinct_coords.empty() || distinct_coords[0] > 1 && g_N_seg > 0) { // Ensure 0 or a value like 1 is present if needed
         // Smallest A_i is 1. So smallest answer is 1 or an element.
         // If all elements are large, 0 might be a valid output if no conditions met.
         // The problem implies finding a value from the array elements or similar.
         // If distinct_coords is empty (N=0), or if all are >0, and we need a "base" answer.
         // For this problem, if N_1 > N_0_seg is never met, what's the answer?
         // It implies we should output the smallest possible value that $A_i$ can take, or 0 if that's appropriate.
         // The lowest value in `distinct_coords` (if sorted non-decreasingly) will be the first `current_best_X`.
    }


    vector<ll> answers(type2_original_indices.size());
    g_tree.resize(4 * g_N_seg + 5); // Allocate segment tree memory

    vector<ll> current_A_state = initial_A;

    for(int q_idx = 0; q_idx < Q_count; ++q_idx) {
        if (queries[q_idx].type == 1) {
            current_A_state[queries[q_idx].p1] = queries[q_idx].val_x;
        } else {
            int l_query = queries[q_idx].p1;
            int r_query = queries[q_idx].p2;
            int ans_idx = queries[q_idx].original_idx_for_ans;

            ll query_ans = 0; // Default answer if no X works (e.g., if all DV positive, this is smallest)
                               // The problem seems to imply result is one of A_i.
                               // The smallest value in distinct_coords (excluding a dummy 0 if added)
                               // could be initial query_ans. The problem asks for MAX value.
            if (!distinct_coords.empty()) query_ans = distinct_coords[0];


            int low_dc_idx = 0, high_dc_idx = distinct_coords.size() - 1;
            
            // If N=0 or L>R, result might be 0 or handled by check.
            // Smallest value in A_i is 1. So 0 is a safe default "no positive value works"
            // However, the median calculation will always yield an element if partitions non-empty.
            // So the "max possible value" will be one of the numbers present in A.
            // Or 0 if no such partition scheme results in the condition.
            // The problem implies result is one of the elements. Smallest element as default.
            query_ans = 0; // Default to 0 if no X works, or use smallest from distinct_coords.
                           // Let's assume 0 is a valid output if condition never met for any X > 0.

            while(low_dc_idx <= high_dc_idx) {
                int mid_dc_idx = low_dc_idx + (high_dc_idx - low_dc_idx) / 2;
                ll X_candidate = distinct_coords[mid_dc_idx];
                
                if (X_candidate == 0 && g_N_seg > 0 && l_query <= r_query) { // Special handling if 0 is in DV and tested
                    // if all A_i are positive, X_candidate=0 means all A_i >= 0 -> all 1s.
                    // Generally, the problem values are positive.
                    // If we must pick a value from current A, then X_candidate shouldn't be 0 unless 0 is in A.
                    // Given 1 <= A_i, X_candidate won't be 0 unless we add it.
                    // We can assume distinct_coords[0] is the smallest actual value if we filter out dummy 0.
                }


                if (check(X_candidate, l_query, r_query, current_A_state)) {
                    query_ans = X_candidate;
                    low_dc_idx = mid_dc_idx + 1;
                } else {
                    high_dc_idx = mid_dc_idx - 1;
                }
            }
            answers[ans_idx] = query_ans;
        }
    }

    for (size_t i = 0; i < answers.size(); ++i) {
        cout << answers[i] << "\n";
    }

    return 0;
}
0