結果

問題 No.649 ここでちょっとQK!
ユーザー Keiichi HirobeKeiichi Hirobe
提出日時 2022-06-18 17:41:11
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 292 ms / 3,000 ms
コード長 5,656 bytes
コンパイル時間 1,219 ms
コンパイル使用メモリ 116,036 KB
実行使用メモリ 7,932 KB
最終ジャッジ日時 2024-10-10 08:21:09
合計ジャッジ時間 7,633 ms
ジャッジサーバーID
(参考情報)
judge2 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,816 KB
testcase_01 AC 2 ms
6,820 KB
testcase_02 AC 2 ms
6,820 KB
testcase_03 AC 292 ms
6,820 KB
testcase_04 AC 189 ms
7,932 KB
testcase_05 AC 188 ms
7,928 KB
testcase_06 AC 178 ms
7,796 KB
testcase_07 AC 2 ms
6,816 KB
testcase_08 AC 2 ms
6,820 KB
testcase_09 AC 2 ms
6,820 KB
testcase_10 AC 2 ms
6,816 KB
testcase_11 AC 2 ms
6,820 KB
testcase_12 AC 116 ms
6,816 KB
testcase_13 AC 114 ms
6,816 KB
testcase_14 AC 115 ms
6,820 KB
testcase_15 AC 116 ms
6,816 KB
testcase_16 AC 114 ms
6,816 KB
testcase_17 AC 125 ms
6,820 KB
testcase_18 AC 137 ms
6,820 KB
testcase_19 AC 151 ms
6,824 KB
testcase_20 AC 162 ms
6,820 KB
testcase_21 AC 174 ms
7,212 KB
testcase_22 AC 184 ms
7,328 KB
testcase_23 AC 196 ms
7,576 KB
testcase_24 AC 210 ms
7,688 KB
testcase_25 AC 221 ms
7,688 KB
testcase_26 AC 231 ms
7,924 KB
testcase_27 AC 3 ms
6,816 KB
testcase_28 AC 2 ms
6,820 KB
testcase_29 AC 3 ms
6,816 KB
testcase_30 AC 78 ms
6,820 KB
testcase_31 AC 78 ms
6,816 KB
testcase_32 AC 2 ms
6,820 KB
testcase_33 AC 2 ms
6,816 KB
testcase_34 AC 2 ms
6,820 KB
testcase_35 AC 2 ms
6,816 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <vector>
#include <cmath>
#include <map>
#include <algorithm>
#include <queue>
#include <iomanip>
// clang-format off
#define rep(i, s ,n) for(int i=s, i##_len=(n); i<i##_len; ++i)
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
#define SZ(x) ((int)(x).size())
using ll = long long;
// 2^60
const ll INF = 1LL << 60;
// lower_bound(ALL(a), 4)
#define ALL(a)  (a).begin(),(a).end()
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
using namespace std;
using Graph = vector<vector<int>>;
// clang-format on

/*
https://algo-logic.info/binary-indexed-tree/
http://hos.ac/slides/20140319_bit.pdf

BITの使い所
* 1点に対する加算で区間和を求めたい時
* 特に、多次元の場合

厳密には、和以外も可能な場合があったり、区間に対する加算もできるが複雑なのでsegment treeを使った方がいい
例えば、以下は対応可能
* 要素をより大きい値にのみ更新
* 区間の最大値を取得


BITの応用

BITとBIT上での二分探索を活用すると、集合を管理して、

a が何番目に小さいか
w 番目に小さい要素 a は何か
というのを以下のように𝑂(𝑙𝑜𝑔𝑛)で高速に取得することが可能です。

add(a,1): 集合への要素aの追加(a番目を1にする)
add(a,-1): 集合への要素aの削除(a番目を1から0にする)
sum(a): a が何番目に小さいか
lower_bound(w): w 番目に小さい要素 a は何か

ただし、この場合aの範囲が10^6を超えてくるとメモリが足りなくなるので座標圧縮が必要

*/

/* BIT: 区間和の更新や計算を行う構造体
    初期値は a_1 = a_2 = ... = a_n = 0
    ・add(i,x): a_i += x とする
    ・sum(i): a_1 + a_2 + ... + a_i を計算する
    計算量は全て O(logn)
    実装の都合上、1-indexであることに注意
*/
template <typename T>
struct BIT
{
    int n;         // 配列の要素数(数列の要素数+1)
    vector<T> bit; // データの格納先
    BIT(int n_) : n(n_ + 1), bit(n, 0) {}

    void add(int i, T x)
    {
        for (int idx = i; idx < n; idx += (idx & -idx))
        {
            bit[idx] += x;
        }
    }

    T sum(int i)
    {
        T s(0);
        for (int idx = i; idx > 0; idx -= (idx & -idx))
        {
            s += bit[idx];
        }
        return s;
    }

    // [l,r)
    T rangeSum(int l, int r)
    {
        return sum(r - 1) - sum(l - 1);
    }

    // a_1 + a_2 + ... + a_x >= w となるような最小のxを求める(ただし a_i >= 0)
    // O(log(n))
    int lower_bound(T w)
    { // a_1 + a_2 + ... + a_x >= w となるような最小の x を求める(ただし a_i >= 0)
        if (w <= 0)
        {
            return 0;
        }
        else
        {
            int x = 0, r = 1;
            while (r < n)
                r = r << 1;
            for (int len = r; len > 0; len = len >> 1)
            { // 長さlenは1段下るごとに半分に
                if (x + len < n && bit[x + len] < w)
                { // 採用するとき
                    w -= bit[x + len];
                    x += len;
                }
            }
            return x + 1;
        }
    }
};

/* BIT2D:
    初期値は全て0
    ・add(h,w,x): (h,w) に x を加算する
    ・sum(h,w): 1≦i≦h かつ 1≦j≦w の範囲の合計値を求める
    ・rangeSum(h1,w1,h2,w2): h1≦i<h2 かつ w1≦j<w2 の範囲の合計値を求める(1-indexed)
    計算量は全て O(logW * logH)
*/
template <typename T>
struct BIT2D
{
    int H, W;
    vector<vector<T>> bit;
    BIT2D(int H_, int W_) { init(H_, W_); }
    void init(int H_, int W_)
    {
        H = H_ + 1;
        W = W_ + 1;
        bit.assign(H, vector<T>(W, 0));
    }

    void add(int h, int w, T x)
    {
        for (int i = h; i < H; i += (i & -i))
        {
            for (int j = w; j < W; j += (j & -j))
            {
                bit[i][j] += x;
            }
        }
    }
    // 1≦i≦h かつ 1≦j≦w
    T sum(int h, int w)
    {
        T s(0);
        for (int i = h; i > 0; i -= (i & -i))
        {
            for (int j = w; j > 0; j -= (j & -j))
            {
                s += bit[i][j];
            }
        }
        return s;
    }

    // h1≦i<h2 かつ w1≦j<w2
    T rangeSum(int h1, int w1, int h2, int w2)
    {
        return sum(h2 - 1, w2 - 1) - sum(h2 - 1, w1 - 1) - sum(h1 - 1, w2 - 1) + sum(h1 - 1, w1 - 1);
    }
};

// https://yukicoder.me/problems/no/649
// 値を追加
// K番目に大きい値を取得して削除

int main()
{
    int Q, K;

    cin >> Q >> K;
    // 1 or 2
    vector<int> C(Q);
    // case 1
    vector<ll> V(Q, -1);
    vector<ll> Map;

    rep(i, 0, Q)
    {
        int which;
        int v;
        cin >> which;
        C[i] = which;
        if (which == 1)
        {
            cin >> V[i];
            Map.push_back(V[i]);
        }
    }

    sort(Map.begin(), Map.end());
    auto itr = unique(Map.begin(), Map.end());
    Map.erase(itr, Map.end());

    BIT<int> bit(Map.size());
    rep(i, 0, Q)
    {
        if (C[i] == 1)
        {
            bit.add(lower_bound(Map.begin(), Map.end(), V[i]) - Map.begin() + 1, 1);
        }
        else
        {
            int idx = bit.lower_bound(K);
            if (idx > Map.size()) {
                cout << -1 << endl;
            } else {
                cout << Map[idx-1] << endl;
                bit.add(idx, -1);
            }
        }
    }
}
0