結果
| 問題 |
No.1297 銅像
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2020-11-24 14:18:13 |
| 言語 | D (dmd 2.109.1) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 4,933 bytes |
| コンパイル時間 | 1,006 ms |
| コンパイル使用メモリ | 121,612 KB |
| 実行使用メモリ | 14,300 KB |
| 最終ジャッジ日時 | 2024-06-22 10:03:31 |
| 合計ジャッジ時間 | 6,714 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 14 WA * 7 |
ソースコード
import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;
class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }
bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }
int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }
// floor(a / b)
Int divFloor(Int)(Int a, Int b) {
return a / b - (((a ^ b) < 0 && a % b != 0) ? 1 : 0);
}
// ceil(a / b)
Int divCeil(Int)(Int a, Int b) {
return a / b + (((a ^ b) > 0 && a % b != 0) ? 1 : 0);
}
enum INF = 10L^^18;
void main() {
try {
for (; ; ) {
const N = readInt();
const C = readLong();
auto A = new long[N];
auto B = new long[N];
foreach (i; 0 .. N) {
A[i] = readLong();
B[i] = readLong();
}
/*
C k^2
+ (A[i] - A[j] - C (i + j + 1)) k
+ (-A[i] * (i + 1) + A[j] * j + C (i * (i + 1) / 2 + j * (j + 1) / 2))
*/
long calc(int i, int j) {
const p = A[i] - A[j] - C * (i + j + 1);
const q = -A[i] * (i + 1) + A[j] * j + C * (1L * i * (i + 1) / 2 + 1L * j * (j + 1) / 2);
long mn = INF;
void check(long k) {
if (i + 1 <= k && k <= j) {
chmin(mn, (C * k + p) * k + q);
}
}
check(i + 1);
check(j);
check(divFloor(-p, 2 * C));
check(divCeil(-p, 2 * C));
return mn;
}
auto dp = new long[N];
foreach (i; 0 .. N) {
dp[i] = A[i] * i + C * i * (i + 1) / 2;
}
auto que = new int[N];
int qb, qe;
foreach (j; 0 .. N) {
long here(int i) {
return dp[i] + calc(i, j);
}
bool cmp(int i0, int i1) {
int lo = j + 1, hi = N;
for (; lo + 1 < hi; ) {
const mid = (lo + hi) / 2;
const res0 = dp[i0] + calc(i0, mid);
const res1 = dp[i1] + calc(i1, mid);
const resj = dp[j] + calc(j, mid);
if (res0 >= res1 && !(res1 >= resj)) return false;
if (!(res0 >= res1) && res1 >= resj) return true;
((res0 >= res1) ? hi : lo) = mid;
}
return false;
}
for (; qe - qb >= 2 && here(que[qb]) >= here(que[qb + 1]); ++qb) {}
if (qe - qb >= 1) {
chmin(dp[j], here(que[qb]));
}
dp[j] += A[j] + B[j];
for (; qe - qb >= 2 && cmp(que[qe - 2], que[qe - 1]); --qe) {}
que[qe++] = j;
}
debug {
writeln("dp = ", dp);
}
long ans = INF;
foreach (i; 0 .. N) {
chmin(ans, dp[i] + A[i] * (N - i - 1) + C * (N - i - 1) * (N - i) / 2);
}
writeln(ans);
debug {
long calcBrute(int i, int j) {
long mn = INF;
foreach (k; i + 1 .. j + 1) {
long cost;
cost += A[i] * (k - i - 1) + C * (k - i - 1) * (k - i) / 2;
cost += A[j] * (j - k) + C * (j - k) * (j - k + 1) / 2;
chmin(mn, cost);
}
return mn;
}
foreach (i; 0 .. N) foreach (j; i + 1 .. N) {
assert(calc(i, j) == calcBrute(i, j));
}
auto brt = new long[N];
brt[] = INF;
foreach (i; 0 .. N) {
chmin(brt[i], A[i] * i + C * i * (i + 1) / 2);
}
foreach (i; 0 .. N) {
brt[i] += A[i] + B[i];
foreach (j; i + 1 .. N) {
chmin(brt[j], brt[i] + calcBrute(i, j));
}
}
writeln("brt = ", brt);
long brtAns = INF;
foreach (i; 0 .. N) {
chmin(brtAns, brt[i] + A[i] * (N - i - 1) + C * (N - i - 1) * (N - i) / 2);
}
writeln("brtAns = ", brtAns);
foreach (i; 0 .. N) foreach (j; i + 1 .. N) {
foreach (k; j + 1 .. N - 1) {
if (brt[i] + calcBrute(i, k) >= brt[j] + calcBrute(j, k)) {
assert(brt[i] + calcBrute(i, k + 1) >= brt[j] + calcBrute(j, k + 1));
}
}
}
}
}
} catch (EOFException e) {
}
}