結果
| 問題 |
No.409 ダイエット
|
| コンテスト | |
| ユーザー |
ngtkana
|
| 提出日時 | 2021-12-19 03:24:30 |
| 言語 | Rust (1.83.0 + proconio) |
| 結果 |
AC
|
| 実行時間 | 400 ms / 2,000 ms |
| コード長 | 7,011 bytes |
| コンパイル時間 | 15,065 ms |
| コンパイル使用メモリ | 378,124 KB |
| 実行使用メモリ | 24,576 KB |
| 最終ジャッジ日時 | 2024-09-15 14:24:14 |
| 合計ジャッジ時間 | 28,100 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge6 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 92 |
ソースコード
use cht_integer::ConvexHullTrick;
#[allow(unused_imports)]
#[cfg(feature = "dbg")]
use dbg::lg;
use proconio::{fastout, input};
use std::iter::once;
#[fastout]
fn main() {
input! {
n: usize,
a: i64,
b: i64,
w: i64,
d: [i64; n],
}
let mut cht = ConvexHullTrick::new();
cht.insert(0, -(2 * w));
for (i, d) in once(0).chain(d.iter().copied()).enumerate() {
let x0 = i as i64;
let y0 = (-cht.eval(x0) + b * x0 * x0) / 2 + d;
let tilt = -2 * a + (-2 * x0 - 1) * b;
let intercept = 2 * y0 + 2 * (x0 + 1) * a + b * x0 * (x0 + 1);
cht.insert(-tilt, -intercept);
}
let end = n as i64 + 1;
let ans = (-cht.eval(end) + b * end * end) / 2;
println!("{}", ans);
}
// cht_integer {{{
#[allow(dead_code)]
mod cht_integer {
use std::{
borrow::Borrow,
collections::BTreeSet,
fmt::Debug,
i64::{MAX, MIN},
};
#[derive(Clone, Debug, Default, Hash, PartialEq)]
pub struct ConvexHullTrick {
set: BTreeSet<Segment>,
}
impl ConvexHullTrick {
pub fn new() -> Self {
Self::default()
}
pub fn multieval(&self, xs: impl Iterator<Item = i64>) -> Vec<i64> {
xs.map(|x| self.eval(x)).collect()
}
pub fn collect_lines(&self) -> Vec<(i64, i64)> {
self.set
.iter()
.map(|&seg| (seg.line.p, -seg.line.q))
.collect()
}
pub fn eval(&self, x: i64) -> i64 {
assert!(
!self.set.is_empty(),
"empty maximum is the negative infinity"
);
self.set.range(Max(x)..).next().unwrap().line.eval(x)
}
pub fn lave(&self, p: i64) -> Option<i64> {
assert!(
!self.set.is_empty(),
"empty maximum is the negative infinity"
);
let &Segment {
line: Line { p: p1, q: q1 },
min: Min(min),
max: _,
} = self.set.range(p..).next()?;
if min == MIN {
if p1 == p {
Some(q1)
} else {
None
}
} else {
Some(q1 - (p1 - p) * min)
}
}
pub fn insert(&mut self, tilt: i64, intercept: i64) -> bool {
let q = -intercept;
let p = tilt;
if !self.set.is_empty() && self.lave(p).map_or(false, |c| c <= q) {
return false;
}
self.set.take(&p);
let line = Line { p, q };
while let Some(&seg1) = self.set.range(..p).next_back() {
if seg1.min.0 == MIN || line.eval(seg1.min.0) < seg1.line.eval(seg1.min.0) {
break;
}
self.set.remove(&seg1);
}
while let Some(&seg1) = self.set.range(p..).next() {
if seg1.max.0 == MAX || line.eval(seg1.max.0) < seg1.line.eval(seg1.max.0) {
break;
}
self.set.remove(&seg1);
}
if let Some(&seg1) = self.set.range(..p).next_back() {
self.set.remove(&seg1);
match seg1.line.brace(line) {
Err(x) => {
debug_assert!(seg1.min.0 < x);
self.set.insert(Segment {
max: Max(x),
..seg1
});
}
Ok(brace) => {
if seg1.min.0 < brace.min.0 {
self.set.insert(Segment {
max: Max(brace.min.0),
..seg1
});
}
self.set.insert(brace);
}
}
}
if let Some(&seg1) = self.set.range(p..).next() {
self.set.remove(&seg1);
match line.brace(seg1.line) {
Err(x) => {
debug_assert!(x < seg1.max.0);
self.set.insert(Segment {
min: Min(x),
..seg1
});
}
Ok(brace) => {
if brace.max.0 < seg1.max.0 {
self.set.insert(Segment {
min: Min(brace.max.0),
..seg1
});
}
self.set.insert(brace);
}
}
}
let min = Min(self
.set
.range(..p)
.next_back()
.map_or(MIN, |seg1| seg1.max.0));
let max = Max(self.set.range(p..).next().map_or(MAX, |seg1| seg1.min.0));
if min.0 < max.0 {
self.set.insert(Segment { line, min, max });
}
true
}
}
#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Copy)]
struct Min(i64);
#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Copy)]
struct Max(i64);
#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Copy)]
struct Line {
p: i64,
q: i64,
}
impl Line {
fn eval(&self, x: i64) -> i64 {
self.p * x - self.q
}
fn brace(self, other: Self) -> Result<Segment, i64> {
let Self { p: p0, q: q0 } = self;
let Self { p: p1, q: q1 } = other;
debug_assert!(p0 < p1);
let x0 = (q1 - q0).div_euclid(p1 - p0);
if x0 * (p1 - p0) == (q1 - q0) {
return Err(x0);
}
let x1 = x0 + 1;
let p = (p1 * x1 - p0 * x0) - (q1 - q0);
let q = (p1 - p0) * x0 * x1 - q1 * x0 + q0 * x1;
debug_assert_eq!(p * x0 - q, p0 * x0 - q0);
debug_assert_eq!(p * x1 - q, p1 * x1 - q1);
Ok(Segment {
line: Self { p, q },
min: Min(x0),
max: Max(x1),
})
}
}
#[derive(Clone, Default, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Copy)]
struct Segment {
line: Line,
min: Min,
max: Max,
}
impl Borrow<i64> for Segment {
fn borrow(&self) -> &i64 {
&self.line.p
}
}
impl Borrow<Min> for Segment {
fn borrow(&self) -> &Min {
&self.min
}
}
impl Borrow<Max> for Segment {
fn borrow(&self) -> &Max {
&self.max
}
}
}
// }}}
// template {{{
#[cfg(not(feature = "dbg"))]
#[allow(unused_macros)]
#[macro_export]
macro_rules! lg {
($($expr:expr),*) => {};
}
// }}}
ngtkana