結果
| 問題 |
No.919 You Are A Project Manager
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2022-03-03 08:17:15 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 7,134 bytes |
| コンパイル時間 | 3,594 ms |
| コンパイル使用メモリ | 235,324 KB |
| 最終ジャッジ日時 | 2025-01-28 04:27:08 |
|
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 39 TLE * 16 |
ソースコード
#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';
}