結果
| 問題 |
No.409 ダイエット
|
| コンテスト | |
| ユーザー |
nanophoto12
|
| 提出日時 | 2021-12-12 20:39:38 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 4,484 bytes |
| コンパイル時間 | 3,760 ms |
| コンパイル使用メモリ | 253,212 KB |
| 最終ジャッジ日時 | 2025-01-26 09:17:49 |
|
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 56 TLE * 36 |
ソースコード
#include <bits/stdc++.h>
#define M_PI 3.14159265358979323846 // pi
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;
typedef tuple<ll, ll, ll> t3;
typedef tuple<ll, ll, ll, ll> t4;
typedef tuple<ll, ll, ll, ll, ll> t5;
#define rep(a,n) for(ll a = 0;a < n;a++)
template<typename T>
static inline void chmin(T& ref, const T value) {
if (ref > value) ref = value;
}
template<typename T>
static inline void chmax(T& ref, const T value) {
if (ref < value) ref = value;
}
#include <atcoder/all>
using namespace atcoder;
typedef modint998244353 mint;
typedef ll CHT_TYPE;
class ConvexHullTrickDynamic {
private:
// 直線 **************************************************************
struct Line {
CHT_TYPE a, b; // y = ax + b
mutable std::function<const Line* ()> getSuc; // 次の直線へのポインタ (ソートで用いる)
bool operator<(const Line& rhs) const {
// 取得クエリでは次の直線との差分でソート
if (rhs.b == IS_QUERY) {
const Line* suc = getSuc();
if (suc == nullptr) return false;
const CHT_TYPE& x = rhs.a;
return (suc->a - a) * x + suc->b - b > 0;
}
if (b == IS_QUERY) {
const Line* suc = rhs.getSuc();
if (suc == nullptr) return true;
const CHT_TYPE& x = a;
return (suc->a - rhs.a) * x + suc->b - rhs.b < 0;
}
// 通常の直線どうしは傾きソート
return a < rhs.a;
}
};
// 直線集合 **********************************************************
class LinesSet {
private:
// true -> 最小値クエリ, false -> 最大値クエリ
bool flagMin;
std::multiset<Line> lines;
public:
// コンストラクタ ( 第一引数falseで最大値クエリ,デフォルトで最小値クエリ )
LinesSet(bool flagMin = true) : flagMin(flagMin) {};
// 直線lが不必要であるかどうか
bool isBad(std::multiset<Line>::iterator l) {
const auto&& nel = std::next(l);
if (l == lines.begin()) { // lが傾き最小のとき
if (nel == lines.end()) return false; // lしかないなら必要
return l->a == nel->a && l->b <= nel->b;
}
else {
const auto&& prl = std::prev(l);
if (nel == lines.end()) return l->a == prl->a && l->b <= prl->b;
return (prl->b - l->b) * (nel->a - l->a) >= (nel->b - l->b) * (prl->a - l->a);
}
}
// 直線y=ax+bを追加する
inline void add(CHT_TYPE a, CHT_TYPE b) {
if (flagMin) a = -a, b = -b;
auto&& it = lines.insert(Line{ a, b });
it->getSuc = [=] { return (std::next(it) == lines.end() ? nullptr : &*std::next(it)); };
if (isBad(it)) { lines.erase(it); return; }
while (std::next(it) != lines.end() && isBad(std::next(it))) lines.erase(std::next(it));
while (it != lines.begin() && isBad(std::prev(it))) lines.erase(std::prev(it));
}
// 直線群の中でxの時に最小(最大)となる値を返す
inline CHT_TYPE get(CHT_TYPE x) {
auto&& l = *lines.lower_bound(Line{ x, IS_QUERY });
if (flagMin) return -l.a * x - l.b;
else return l.a * x + l.b;
}
};
static const CHT_TYPE IS_QUERY = std::numeric_limits<CHT_TYPE>::lowest();
LinesSet linesSet;
public:
// コンストラクタ ( 第一引数falseで最大値クエリ,デフォルトで最小値クエリ )
ConvexHullTrickDynamic(bool flagMin = true) : linesSet(flagMin) {}
// 直線y=ax+bを追加する
inline void add(CHT_TYPE a, CHT_TYPE b) { linesSet.add(a, b); }
// あるxのときの直線集合での最小値を求める
inline CHT_TYPE get(CHT_TYPE x) { return linesSet.get(x); }
};
int main() {
//dp[i]...i日目に最後のドーナツをたべたときの最小値
//dp[i]...min(dp[0] + b * (1 + 2 + 3 + ... i) - a * i,
// dp[1] + b * (1 + 2 + 3 + ... + i-1) - a * (i-1)
//dp[j] + (i-j) * (i-j+1)/2 - a * (i-j);
//a = (-j+1) + (-j) / 2
ll n, a, b, w;
cin >> n >> a >> b >> w;
vector<ll> ds(n + 2, 0);
rep(i, n) cin >> ds[i + 1];
vector<ll> dp(n + 2, 1e15);
dp[0] = 0;
ConvexHullTrickDynamic cht;
for (int i = 1; i <= n + 1; i++) {
ll low = 1e15;
ll ci = i - 1;
for (int j = 0; j < i; j++) {
ll p = dp[j] + b * (ci - j) * (ci - j + 1) / 2 - a * (ci - j);
//dp[j] + b * (-j+1) ci / 2+ -b * j * ci / 2+ b * ci * ci / 2+ b * j * (j-1) / 2
// -a * ci + a * j;
//A = - b * j / 2+ b * (-j+1) / 2- a;
//B = dp[j] + b * j * (j-1) / 2 + a * j
//C = b * ci * ci / 2
chmin(low, p);
}
dp[i] = low + ds[i];
}
ll ans = w + dp[n + 1];
cout << ans << endl;
return 0;
}
nanophoto12