結果

問題 No.2223 Merged Med
ユーザー gyouzasushigyouzasushi
提出日時 2023-02-17 23:10:40
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 6,537 bytes
コンパイル時間 2,461 ms
コンパイル使用メモリ 221,200 KB
実行使用メモリ 15,004 KB
最終ジャッジ日時 2024-07-19 14:22:38
合計ジャッジ時間 13,107 ms
ジャッジサーバーID
(参考情報)
judge1 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,812 KB
testcase_01 AC 2 ms
6,940 KB
testcase_02 AC 2 ms
6,944 KB
testcase_03 AC 2 ms
6,944 KB
testcase_04 WA -
testcase_05 WA -
testcase_06 AC 1 ms
6,940 KB
testcase_07 WA -
testcase_08 WA -
testcase_09 WA -
testcase_10 WA -
testcase_11 AC 1 ms
6,944 KB
testcase_12 WA -
testcase_13 WA -
testcase_14 WA -
testcase_15 TLE -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
testcase_19 -- -
testcase_20 -- -
testcase_21 -- -
testcase_22 -- -
testcase_23 -- -
testcase_24 -- -
testcase_25 -- -
testcase_26 -- -
testcase_27 -- -
testcase_28 -- -
testcase_29 -- -
testcase_30 -- -
testcase_31 -- -
testcase_32 -- -
testcase_33 -- -
testcase_34 -- -
testcase_35 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rrep(i, n) for (int i = (int)(n - 1); i >= 0; i--)
#define all(x) (x).begin(), (x).end()
#define sz(x) int(x.size())
using namespace std;
using ll = long long;
const int INF = 1e9;
const ll LINF = 1e18;
template <class T>
void get_unique(vector<T> &x) {
    x.erase(unique(x.begin(), x.end()), x.end());
}
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;
}
template <class T>
vector<T> make_vec(size_t a) {
    return vector<T>(a);
}
template <class T, class... Ts>
auto make_vec(size_t a, Ts... ts) {
    return vector<decltype(make_vec<T>(ts...))>(a, make_vec<T>(ts...));
}
template <typename T>
istream &operator>>(istream &is, vector<T> &v) {
    for (int i = 0; i < int(v.size()); i++) {
        is >> v[i];
    }
    return is;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
    for (int i = 0; i < int(v.size()); i++) {
        os << v[i];
        if (i < sz(v) - 1) os << ' ';
    }
    return os;
}
// すでに追加したものを削除できるslope trick
// Query query(): Query{lx,rx,min_f}を返す,[lx,rx]でmin_fを取る
// add_all(T a): f(x)にaを加算する
// add_a_minus_x(T a): f(x)にmax(a-x,0)を加算する, \_
// add_x_minus_a(T a): f(x)にmax(x-a,0)を加算する, _/
// add_abs(T a): f(x)に|x-a|を加算する, \/
// erase_a_minus_x(T a): f(x)からmax(a-x,0)を削除する, \_
// erase_x_minus_a(T a): f(x)からmax(x-a,0)を削除する, _/
// erase_abs(T a): f(x)から|x-a|を削除する, \/
// clear_right(): f(x)<-min(f(t)),t<=x , \_/ -> \_
// clear_left(): f(x)<-min(f(t)),x<=t , \_/ -> _/
// shift(T a,T b): f(x)<-min(f(t)),x-b<=t<=x-a
// shift(T a): f(x)<-f(x-a),shift(a,a)してるだけ
// get(T x): f(x)を返す, fを破壊しO(sz(L)+sz(R))
// merge(SlopeTrick x): f(x)にg(x)を加算する, gを破壊する
// 中央値管理に使用したい時はadd_abs(a)していってlxなりrxなりを取ればよい

template <typename T>
struct ErasableSlopeTrick {
    const T INF = numeric_limits<T>::max() / 3;

    multiset<T> MS_l, MS_r;
    T min_f, offset_l, offset_r;

private:
    void insert_R(const T &a) {
        MS_r.insert(a - offset_r);
    }

    T top_R() const {
        if (MS_r.empty())
            return INF;
        else
            return *MS_r.begin() + offset_r;
    }

    T pop_R() {
        T val = top_R();
        if (!MS_r.empty()) MS_r.erase(MS_r.find(val - offset_r));
        return val;
    }

    void insert_L(const T &a) {
        MS_l.insert(a - offset_l);
    }

    T top_L() const {
        if (MS_l.empty())
            return -INF;
        else
            return *--MS_l.end() + offset_l;
    }

    T pop_L() {
        T val = top_L();
        if (!MS_l.empty()) MS_l.erase(MS_l.find(val - offset_l));
        return val;
    }

    size_t size() {
        return MS_l.size() + MS_r.size();
    }

public:
    ErasableSlopeTrick() : min_f(0), offset_l(0), offset_r(0) {
    }

    struct Query {
        T lx, rx, min_f;
    };

    Query query() const {
        return (Query){top_L(), top_R(), min_f};
    }

    void add_all(const T &a) {
        min_f += a;
    }

    void add_a_minus_x(const T &a) {
        insert_R(a);
        insert_L(pop_R());
        min_f += max(T(0), a - top_L());
    }

    void add_x_minus_a(const T &a) {
        insert_L(a);
        insert_R(pop_L());
        min_f += max(T(0), top_R() - a);
    }

    void add_abs(const T &a) {
        add_a_minus_x(a);
        add_x_minus_a(a);
    }

    void erase_a_minus_x(const T &a) {
        if (MS_l.find(a - offset_l) == MS_l.end()) {
            MS_r.erase(MS_r.find(a - offset_r));
            insert_R(pop_L());
        } else {
            MS_l.erase(MS_l.find(a - offset_l));
        }
        min_f -= max(T(0), a - top_R());
    }

    void erase_x_minus_a(const T &a) {
        if (MS_l.find(a - offset_l) == MS_l.end()) {
            MS_r.erase(MS_r.find(a - offset_r));
        } else {
            MS_l.erase(MS_l.find(a - offset_l));
            insert_L(pop_R());
        }
        min_f -= max(T(0), top_L() - a);
    }

    void erase_abs(const T &a) {
        erase_a_minus_x(a);
        erase_x_minus_a(a);
    }

    void clear_right() {
        if (!MS_r.empty()) MS_r.clear();
    }

    void clear_left() {
        if (!MS_l.empty()) MS_l.clear();
    }

    void shift(const T &a, const T &b) {
        assert(a <= b);
        offset_l += a;
        offset_r += b;
    }

    void shift(const T &a) {
        shift(a, a);
    }

    T get(const T &x) {
        T ret = min_f;
        while (!MS_l.empty()) ret += max(T(0), pop_L() - x);
        while (!MS_r.empty()) ret += max(T(0), x - pop_R());
        return ret;
    }

    void merge(ErasableSlopeTrick &st) {
        if (st.size() > size()) {
            swap(st.MS_l, MS_l);
            swap(st.MS_r, MS_r);
            swap(st.min_f, min_f);
            swap(st.offset_l, offset_l);
            swap(st.offset_r, offset_r);
        }
        while (!st.MS_r.empty()) add_x_minus_a(st.pop_R());
        while (!st.MS_l.empty()) add_a_minus_x(st.pop_L());
        min_f += st.min_f;
    }
};
int main() {
    int n, q;
    cin >> n >> q;
    vector<int> a(n);
    cin >> a;
    using T = tuple<int, int, int>;
    vector<T> qs(q);
    rep(i, q) {
        int l, r;
        cin >> l >> r;
        qs[i] = T(--l, r, i);
    }
    const int m = sqrt(q);
    sort(all(qs), [&](T a, T b) {
        auto [la, ra, ia] = a;
        auto [lb, rb, ib] = b;
        if (la / m != lb / m) return la / m < lb / m;
        return (la / m & 1) ? ra > rb : ra < rb;
    });
    ErasableSlopeTrick<int> st;
    vector<int> ans(q);
    int l = 0, r = 0;
    for (auto [nl, nr, i] : qs) {
        while (l > nl) {
            l--;
            st.add_abs(a[l]);
        }
        while (r < nr) {
            st.add_abs(a[r]);
            r++;
        }
        while (l < nl) {
            st.erase_abs(a[l]);
            l++;
        }
        while (r > nr) {
            r--;
            st.erase_abs(a[r]);
        }
        ans[i] = st.query().rx;
        if (nl + 1 < nr) {
            chmin(ans[i], max(a[nl], a[nl + 1]));
            chmin(ans[i], max(a[nr - 1], a[nr - 2]));
            chmin(ans[i], max(a[nl], a[nr - 1]));
        }
    }
    rep(i, q) cout << ans[i] << '\n';
}
0