結果
問題 | No.913 木の燃やし方 |
ユーザー | niuez |
提出日時 | 2019-10-22 16:30:10 |
言語 | Rust (1.77.0 + proconio) |
結果 |
AC
|
実行時間 | 445 ms / 3,000 ms |
コード長 | 6,405 bytes |
コンパイル時間 | 14,788 ms |
コンパイル使用メモリ | 385,912 KB |
実行使用メモリ | 9,944 KB |
最終ジャッジ日時 | 2024-07-04 03:32:19 |
合計ジャッジ時間 | 29,381 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1 ms
6,812 KB |
testcase_01 | AC | 2 ms
6,812 KB |
testcase_02 | AC | 2 ms
6,944 KB |
testcase_03 | AC | 6 ms
6,944 KB |
testcase_04 | AC | 6 ms
6,940 KB |
testcase_05 | AC | 7 ms
6,940 KB |
testcase_06 | AC | 5 ms
6,944 KB |
testcase_07 | AC | 3 ms
6,940 KB |
testcase_08 | AC | 445 ms
6,940 KB |
testcase_09 | AC | 382 ms
6,944 KB |
testcase_10 | AC | 361 ms
6,944 KB |
testcase_11 | AC | 371 ms
6,944 KB |
testcase_12 | AC | 391 ms
6,944 KB |
testcase_13 | AC | 386 ms
7,040 KB |
testcase_14 | AC | 391 ms
6,940 KB |
testcase_15 | AC | 411 ms
6,944 KB |
testcase_16 | AC | 405 ms
6,944 KB |
testcase_17 | AC | 374 ms
6,940 KB |
testcase_18 | AC | 357 ms
6,944 KB |
testcase_19 | AC | 337 ms
9,628 KB |
testcase_20 | AC | 360 ms
7,040 KB |
testcase_21 | AC | 384 ms
6,948 KB |
testcase_22 | AC | 367 ms
6,940 KB |
testcase_23 | AC | 372 ms
6,940 KB |
testcase_24 | AC | 343 ms
6,940 KB |
testcase_25 | AC | 318 ms
8,004 KB |
testcase_26 | AC | 381 ms
7,168 KB |
testcase_27 | AC | 355 ms
9,944 KB |
testcase_28 | AC | 354 ms
6,940 KB |
testcase_29 | AC | 366 ms
6,940 KB |
testcase_30 | AC | 374 ms
6,944 KB |
testcase_31 | AC | 338 ms
9,196 KB |
testcase_32 | AC | 339 ms
9,580 KB |
testcase_33 | AC | 333 ms
9,636 KB |
testcase_34 | AC | 360 ms
6,944 KB |
testcase_35 | AC | 377 ms
6,944 KB |
testcase_36 | AC | 376 ms
6,944 KB |
ソースコード
use std::ops::{ Add, Sub, Mul }; pub trait LineDecimal: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Copy + PartialOrd {} impl LineDecimal for i64 {} impl LineDecimal for f64 {} pub struct Line<T: LineDecimal> { pub a: T, pub b: T, } impl<T: LineDecimal> Line<T> { pub fn new(a: T, b: T) -> Self { Line { a, b } } pub fn get(&self, x: T) -> T { self.a * x + self.b } } impl<T: LineDecimal> Clone for Line<T> { fn clone(&self) -> Self { Line { a: self.a, b: self.b } } } use std::collections::VecDeque; pub struct MonotoneCHT<T: LineDecimal> { lines: VecDeque<Line<T>>, } impl<T: LineDecimal> MonotoneCHT<T> { pub fn new() -> Self { MonotoneCHT { lines: VecDeque::new() } } fn check(ln0: &Line<T>, ln1: &Line<T>, ln2: &Line<T>) -> bool { if ln0.a == ln1.a { ln0.b < ln1.b } else if ln1.a == ln2.a { ln1.b > ln2.b } else { (ln1.b - ln0.b) * (ln1.a - ln2.a) >= (ln2.b - ln1.b) * (ln0.a - ln1.a) } } pub fn push_front(&mut self, ln: Line<T>) { while 1 < self.lines.len() && MonotoneCHT::check(&ln, &self.lines[0], &self.lines[1]) { self.lines.pop_front(); } self.lines.push_front(ln); } pub fn push_back(&mut self, ln: Line<T>) { while 1 < self.lines.len() && MonotoneCHT::check(&self.lines[self.lines.len() - 2], &self.lines[self.lines.len() - 1], &ln) { self.lines.pop_back(); } self.lines.push_back(ln); } pub fn min_value(&self, x: T) -> T { let mut ok = 0; let mut ng = self.lines.len(); while ng - ok > 1 { let mid = (ok + ng) / 2; let ln0 = &self.lines[mid - 1]; let ln1 = &self.lines[mid]; if (ln1.b - ln0.b) <= x * (ln0.a - ln1.a) { ok = mid; } else { ng = mid; } } self.lines[ok].get(x) } pub fn incl_query(&self) -> MonotoneCHTInclQuery<T> { MonotoneCHTInclQuery { lines: &self.lines, i: 0 } } pub fn deq_query(&self) -> MonotoneCHTDeqQuery<T> { MonotoneCHTDeqQuery { lines: &self.lines, i: self.lines.len() - 1 } } } pub struct MonotoneCHTInclQuery<'a, T: LineDecimal> { lines: &'a VecDeque<Line<T>>, i: usize, } impl<'a, T: LineDecimal> MonotoneCHTInclQuery<'a, T> { pub fn min_value(&mut self, x: T) -> T { while self.i + 1 < self.lines.len() && self.lines[self.i].get(x) >= self.lines[self.i + 1].get(x) { self.i += 1; } self.lines[self.i].get(x) } } pub struct MonotoneCHTDeqQuery<'a, T: LineDecimal> { lines: &'a VecDeque<Line<T>>, i: usize, } impl<'a, T: LineDecimal> MonotoneCHTDeqQuery<'a, T> { pub fn min_value(&mut self, x: T) -> T { while self.i > 0 && self.lines[self.i].get(x) >= self.lines[self.i - 1].get(x) { self.i -= 1; } self.lines[self.i].get(x) } } /// Reading from standard input /// /// `input!` is useful for competition programming. /// There are some forms. /// /// - Tuple /// /// ``` /// use cp_rust_library::*; /// input! { source = "2 3", ab: (usize, usize), } /// assert_eq!(ab.0, 2); /// assert_eq!(ab.1, 3); /// ``` /// /// - Array /// ``` /// use cp_rust_library::*; /// input! { source = "1 2 3 4", a: [usize; 4], } /// assert_eq!(a, vec![1, 2, 3, 4]); /// ``` /// /// - String -> Vec<char> /// ``` /// use cp_rust_library::*; /// input! { source = "qwerty", s: chars, } /// assert_eq!('q', s[0]); /// ``` /// /// - Other /// ``` /// use cp_rust_library::*; /// input! { source = "123", a: usize, } /// assert_eq!(123, a); /// ``` /// /// This macro will use parse::<$type>() to parse string. #[macro_export] macro_rules! input { (source = $s:expr, $($r:tt)*) => { let mut iter = $s.split_whitespace(); input_rec!{ iter, $($r)* } }; ($($r:tt)*) => { let s = { use std::io::Read; let mut s = String::new(); std::io::stdin().read_to_string(&mut s).unwrap(); s }; let mut iter = s.split_whitespace(); input_rec!{ iter, $($r)* } }; } #[macro_export] macro_rules! input_rec { ($iter:expr) => {}; ($iter:expr, ) => {}; ($iter:expr, $var:ident : $t:tt, $($r:tt)*) => { let $var = read_value!($iter, $t); input_rec! { $iter, $($r)* } }; } #[macro_export] macro_rules! read_value { // tuple ($iter:expr, ( $($t:tt), * )) => { ( $(read_value!($iter, $t)), * ) }; // array ($iter:expr, [ $t:tt; $len:expr ]) => { (0..$len).map(|_| { read_value!($iter, $t) }).collect::<Vec<_>>() }; // string ($iter:expr, chars) => { read_value!($iter, String).chars().collect::<Vec<char>>() }; // any other ($iter:expr, $t:ty) => { $iter.next().unwrap().parse::<$t>().expect("Parse error") }; } fn rec(l: usize, r: usize, s: &Vec<i64>, ans: &mut Vec<i64>) { if r <= l { return; } let m = (l + r) / 2; rec(l, m, s, ans); rec(m + 1, r, s, ans); { let mut cht = MonotoneCHT::new(); for ri in m+1..r+1 { let rr = ri as i64; cht.push_back(Line::new(-2i64 * rr, rr * rr + s[0] - s[ri])); } let mut qry = cht.incl_query(); let mut now = 1e18 as i64; for i in l..m { let ii = i as i64; now = std::cmp::min(now, qry.min_value(ii) + ii * ii - s[0] + s[i]); ans[i] = std::cmp::min(ans[i], now); } } { let mut cht = MonotoneCHT::new(); for li in l..m+1 { let ll = li as i64; cht.push_back(Line::new(-2i64 * ll, ll * ll - s[0] + s[li])); } let mut qry = cht.deq_query(); let mut now = 1e18 as i64; for i in (m+1..r+1).rev() { let ii = i as i64; now = std::cmp::min(now, qry.min_value(ii) + ii * ii + s[0] - s[i]); ans[i - 1] = std::cmp::min(ans[i - 1], now); } } } fn main() { input! { n: usize, a: [i64; n], } let mut s = a; s.push(0); for i in (0..n).rev() { s[i] += s[i + 1]; } let mut ans = vec![0i64; n]; for i in 0..n { ans[i] = 1 + s[i] - s[i + 1]; } rec(0, n, &s, &mut ans); for i in 0..n { println!("{}", ans[i]); } }