結果

問題 No.919 You Are A Project Manager
ユーザー gyouzasushigyouzasushi
提出日時 2022-03-03 08:17:15
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
TLE  
実行時間 -
コード長 7,134 bytes
コンパイル時間 3,266 ms
コンパイル使用メモリ 244,084 KB
実行使用メモリ 21,648 KB
最終ジャッジ日時 2023-09-24 04:47:02
合計ジャッジ時間 13,595 ms
ジャッジサーバーID
(参考情報)
judge15 / judge12
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 TLE -
testcase_01 AC 2 ms
4,380 KB
testcase_02 AC 2 ms
4,376 KB
testcase_03 AC 1 ms
4,376 KB
testcase_04 AC 325 ms
6,212 KB
testcase_05 AC 365 ms
6,520 KB
testcase_06 AC 12 ms
4,380 KB
testcase_07 AC 962 ms
8,760 KB
testcase_08 AC 121 ms
4,668 KB
testcase_09 AC 75 ms
4,576 KB
testcase_10 AC 170 ms
5,220 KB
testcase_11 AC 157 ms
4,988 KB
testcase_12 AC 3 ms
4,384 KB
testcase_13 AC 235 ms
5,744 KB
testcase_14 AC 6 ms
4,380 KB
testcase_15 AC 41 ms
4,380 KB
testcase_16 AC 392 ms
6,264 KB
testcase_17 TLE -
testcase_18 TLE -
testcase_19 TLE -
testcase_20 TLE -
testcase_21 TLE -
testcase_22 AC 1,092 ms
9,148 KB
testcase_23 AC 1,054 ms
8,900 KB
testcase_24 AC 1,146 ms
9,156 KB
testcase_25 AC 1,086 ms
9,224 KB
testcase_26 TLE -
testcase_27 AC 2,786 ms
13,992 KB
testcase_28 TLE -
testcase_29 TLE -
testcase_30 TLE -
testcase_31 TLE -
testcase_32 TLE -
testcase_33 AC 1,254 ms
9,772 KB
testcase_34 AC 1,247 ms
9,804 KB
testcase_35 TLE -
testcase_36 -- -
testcase_37 -- -
testcase_38 -- -
testcase_39 -- -
testcase_40 -- -
testcase_41 -- -
testcase_42 -- -
testcase_43 -- -
testcase_44 -- -
testcase_45 -- -
testcase_46 -- -
testcase_47 -- -
testcase_48 -- -
testcase_49 -- -
testcase_50 -- -
testcase_51 -- -
testcase_52 -- -
testcase_53 -- -
testcase_54 -- -
testcase_55 -- -
testcase_56 -- -
testcase_57 -- -
権限があれば一括ダウンロードができます

ソースコード

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>
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 < int(v.size()) - 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;
    cin >> n;
    vector<ll> a(n);
    cin >> a;

    vector<pair<int, int>> qs;
    for (int k = 1; k <= n; k++) {
        for (int l = 0, r = k; r <= n; l += k, r += k) {
            qs.emplace_back(l, r);
        }
    }
    const int m = sqrt(sz(qs));
    sort(all(qs), [&](auto a, auto b) {
        auto [la, ra] = a;
        auto [lb, rb] = b;
        if (la / m != lb / m) return la / m < lb / m;
        return (la / m & 1) ? ra > rb : ra < rb;
    });

    vector maxs(2, vector<vector<ll>>(n + 1));
    vector<ErasableSlopeTrick<ll>> est(2);
    vector meds(2, vector<unordered_map<ll, ll>>(n + 1));

    int l = 0, r = 0;
    for (auto [nl, nr] : qs) {
        while (l > nl) {
            --l;
            est[0].add_abs(a[l]);
            est[1].add_abs(a[n - 1 - l]);
        }
        while (r < nr) {
            est[0].add_abs(a[r]);
            est[1].add_abs(a[n - 1 - r]);
            r++;
        }
        while (l < nl) {
            est[0].erase_abs(a[l]);
            est[1].erase_abs(a[n - 1 - l]);
            l++;
        }
        while (r > nr) {
            --r;
            est[0].erase_abs(a[r]);
            est[1].erase_abs(a[n - 1 - r]);
        }
        meds[0][nl][nr] = est[0].query().lx;
        meds[1][nl][nr] = est[1].query().lx;
    }

    rep(i, 2) {
        for (int k = 1; k <= n; k++) {
            ll mx = 0, sm = 0;
            maxs[i][k] = {0};
            for (int l = 0, r = k; r <= n; l += k, r += k) {
                chmax(mx, sm + meds[i][l][r]);
                sm += meds[i][l][r];
                maxs[i][k].push_back(mx);
            }
        }
    }

    ll ans = 0;
    for (ll k = 1; k <= n; k++) {
        int x = sz(maxs[0][k]);
        for (int i = 0; i < x; i++) {
            chmax(ans, k * (maxs[0][k][i] + maxs[1][k][x - 1 - i]));
        }
    }
    cout << ans << '\n';
}
0