結果

問題 No.738 平らな農地
ユーザー koba-e964koba-e964
提出日時 2021-09-28 11:02:57
言語 Rust
(1.77.0 + proconio)
結果
AC  
実行時間 277 ms / 2,000 ms
コード長 7,601 bytes
コンパイル時間 11,327 ms
コンパイル使用メモリ 378,820 KB
実行使用メモリ 9,216 KB
最終ジャッジ日時 2024-07-07 14:24:55
合計ジャッジ時間 19,771 ms
ジャッジサーバーID
(参考情報)
judge3 / judge5
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 0 ms
5,248 KB
testcase_01 AC 1 ms
5,376 KB
testcase_02 AC 1 ms
5,376 KB
testcase_03 AC 1 ms
5,376 KB
testcase_04 AC 1 ms
5,376 KB
testcase_05 AC 2 ms
5,376 KB
testcase_06 AC 3 ms
5,376 KB
testcase_07 AC 3 ms
5,376 KB
testcase_08 AC 1 ms
5,376 KB
testcase_09 AC 1 ms
5,376 KB
testcase_10 AC 1 ms
5,376 KB
testcase_11 AC 2 ms
5,376 KB
testcase_12 AC 2 ms
5,376 KB
testcase_13 AC 3 ms
5,376 KB
testcase_14 AC 2 ms
5,376 KB
testcase_15 AC 120 ms
5,376 KB
testcase_16 AC 131 ms
5,376 KB
testcase_17 AC 113 ms
5,376 KB
testcase_18 AC 112 ms
5,376 KB
testcase_19 AC 76 ms
5,376 KB
testcase_20 AC 123 ms
5,504 KB
testcase_21 AC 118 ms
5,376 KB
testcase_22 AC 124 ms
5,376 KB
testcase_23 AC 110 ms
5,376 KB
testcase_24 AC 97 ms
5,376 KB
testcase_25 AC 1 ms
5,376 KB
testcase_26 AC 1 ms
5,376 KB
testcase_27 AC 2 ms
5,376 KB
testcase_28 AC 1 ms
5,376 KB
testcase_29 AC 1 ms
5,376 KB
testcase_30 AC 1 ms
5,376 KB
testcase_31 AC 1 ms
5,376 KB
testcase_32 AC 2 ms
5,376 KB
testcase_33 AC 1 ms
5,376 KB
testcase_34 AC 1 ms
5,376 KB
testcase_35 AC 1 ms
5,376 KB
testcase_36 AC 1 ms
5,376 KB
testcase_37 AC 1 ms
5,376 KB
testcase_38 AC 1 ms
5,376 KB
testcase_39 AC 1 ms
5,376 KB
testcase_40 AC 1 ms
5,376 KB
testcase_41 AC 1 ms
5,376 KB
testcase_42 AC 1 ms
5,376 KB
testcase_43 AC 1 ms
5,376 KB
testcase_44 AC 1 ms
5,376 KB
testcase_45 AC 117 ms
6,528 KB
testcase_46 AC 109 ms
5,632 KB
testcase_47 AC 113 ms
6,272 KB
testcase_48 AC 104 ms
6,528 KB
testcase_49 AC 106 ms
6,656 KB
testcase_50 AC 110 ms
6,912 KB
testcase_51 AC 117 ms
6,016 KB
testcase_52 AC 107 ms
5,888 KB
testcase_53 AC 109 ms
6,016 KB
testcase_54 AC 119 ms
6,144 KB
testcase_55 AC 122 ms
5,888 KB
testcase_56 AC 115 ms
5,888 KB
testcase_57 AC 106 ms
5,888 KB
testcase_58 AC 110 ms
6,272 KB
testcase_59 AC 115 ms
6,912 KB
testcase_60 AC 109 ms
6,912 KB
testcase_61 AC 111 ms
6,656 KB
testcase_62 AC 105 ms
6,144 KB
testcase_63 AC 123 ms
6,144 KB
testcase_64 AC 115 ms
6,272 KB
testcase_65 AC 11 ms
5,376 KB
testcase_66 AC 12 ms
5,376 KB
testcase_67 AC 67 ms
5,888 KB
testcase_68 AC 70 ms
6,144 KB
testcase_69 AC 72 ms
5,376 KB
testcase_70 AC 79 ms
5,760 KB
testcase_71 AC 241 ms
5,376 KB
testcase_72 AC 238 ms
5,376 KB
testcase_73 AC 217 ms
5,632 KB
testcase_74 AC 241 ms
5,376 KB
testcase_75 AC 70 ms
5,376 KB
testcase_76 AC 74 ms
5,632 KB
testcase_77 AC 57 ms
5,376 KB
testcase_78 AC 62 ms
5,376 KB
testcase_79 AC 82 ms
5,376 KB
testcase_80 AC 83 ms
5,504 KB
testcase_81 AC 71 ms
5,376 KB
testcase_82 AC 63 ms
5,376 KB
testcase_83 AC 255 ms
5,376 KB
testcase_84 AC 277 ms
5,376 KB
testcase_85 AC 16 ms
5,376 KB
testcase_86 AC 21 ms
5,376 KB
testcase_87 AC 70 ms
9,216 KB
testcase_88 AC 64 ms
8,960 KB
testcase_89 AC 1 ms
5,376 KB
testcase_90 AC 1 ms
5,376 KB
testcase_91 AC 0 ms
5,376 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

use std::cmp::*;
// https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

macro_rules! read_value {
    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };
    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

// http://www.prefield.com/algorithm/container/avl_tree.html
// https://atcoder.jp/contests/ttpc2019/tasks/ttpc2019_h
// https://atcoder.jp/contests/ttpc2019/submissions/23366439
#[derive(Clone)]
struct Node {
    p: i64,
    sum: i64,
    size: usize,
    height: i32,
    ch: [Option<Box<Node>>; 2],
}

impl Node {
    fn new(p: i64) -> Self {
        Node {
            p: p,
            sum: p,
            size: 1,
            height: 1,
            ch: [None, None],
        }
    }
    // Insert a single element represented as a leaf node.
    fn insert(l: Option<Box<Node>>, x: Node) -> Option<Box<Node>> {
        let mut t = match l {
            None => return Some(Box::new(x)),
            Some(l) => l,
        };
        if t.p <= x.p {
            t.ch[0] = Node::insert(t.ch[0].take(), x);
        } else {
            t.ch[1] = Node::insert(t.ch[1].take(), x);
        }
        Node::cons(&mut t);
        Some(Node::balance(t))
    }
    fn erase(l: Option<Box<Node>>, p: i64) -> Option<Box<Node>> {
        let mut t = match l {
            None => return None,
            Some(l) => l,
        };
        if t.p == p {
            return Node::move_down(t.ch[0].take(), t.ch[1].take());
        }
        if t.p < p {
            t.ch[0] = Node::erase(t.ch[0].take(), p);
        } else {
            t.ch[1] = Node::erase(t.ch[1].take(), p);
        }
        Node::cons(&mut t);
        Some(Node::balance(t))
    }
    fn move_down(l: Option<Box<Node>>, r: Option<Box<Node>>) -> Option<Box<Node>> {
        let mut t = match l {
            None => return r,
            Some(l) => l
        };
        t.ch[1] = Node::move_down(t.ch[1].take(), r);
        Some(Node::balance(t))
    }
    fn len(t: &Option<Box<Node>>) -> usize {
        if let &Some(ref x) = t {
            x.size
        } else {
            0
        }
    }
    fn ht(t: &Option<Box<Node>>) -> i32 {
        if let &Some(ref x) = t {
            x.height
        } else {
            0
        }
    }
    fn sum(t: &Option<Box<Node>>) -> i64 {
        if let &Some(ref x) = t {
            x.sum
        } else {
            0
        }
    }
    fn at(l: &Option<Box<Node>>, pos: usize) -> Option<i64> {
        let t = match l {
            None => return None,
            Some(l) => l,
        };
        if pos >= t.size {
            return None;
        }
        let ll = Node::len(&t.ch[0]);
        if pos < ll {
            return Node::at(&t.ch[0], pos);
        }
        if pos == ll {
            return Some(t.p);
        }
        Node::at(&t.ch[1], pos - ll - 1)
    }
    fn acc(l: &Option<Box<Node>>, pos: usize) -> i64 {
        let t = match l {
            None => return 0,
            Some(l) => l,
        };
        if pos >= t.size {
            return t.sum;
        }
        let ll = Node::len(&t.ch[0]);
        if pos <= ll {
            return Node::acc(&t.ch[0], pos);
        }
        let ls = Node::sum(&t.ch[0]);
        ls + t.p + Node::acc(&t.ch[1], pos - ll - 1)
    }
    // Make t consistent.
    fn cons(t: &mut Box<Self>) {
        for i in 0..2 {
            if let &Some(ref c) = &t.ch[i] {
                assert!(if i == 0 { t.p <= c.p } else { t.p >= c.p }, "i = {}. t.p = {}, c.p = {}", i, t.p, c.p);
            }
        }
        t.height = std::cmp::max(Node::ht(&t.ch[0]), Node::ht(&t.ch[1])) + 1;
        t.size = 1 + Node::len(&t.ch[0]) + Node::len(&t.ch[1]);
        t.sum = t.p + Node::sum(&t.ch[0]) + Node::sum(&t.ch[1]);
    }
    fn rotate(mut t: Box<Self>, l: usize, r: usize) -> Box<Self> {
        let mut s = t.ch[r].take().unwrap();
        t.ch[r] = s.ch[l].take();
        Node::cons(&mut t);
        s.ch[l] = Some(Self::balance(t));
        Node::cons(&mut s);
        Self::balance(s)
    }
    fn balance(mut t: Box<Self>) -> Box<Self> {
        for i in 0..2 {
            if Self::ht(&t.ch[1 - i]) - Self::ht(&t.ch[i]) < -1 {
                let tmp = t.ch[i].as_mut().unwrap();
                if Self::ht(&tmp.ch[1 - i]) - Self::ht(&tmp.ch[i]) > 0 {
                    *tmp = 
                        Self::rotate(std::mem::replace(tmp, Box::new(Node::new(0))), i, 1 - i);
                }
                return Self::rotate(t, 1 - i , i);
            }
        }
        Node::cons(&mut t);
        t
    }
    fn each<F: FnMut(i64)>(t: &Option<Box<Self>>, f: &mut F) {
        let t = match t {
            None => return,
            Some(t) => t,
        };
        Node::each(&t.ch[0], f);
        f(t.p);
        Node::each(&t.ch[1], f);
    }
}

#[derive(Clone)]
struct AVLTree {
    root: Option<Box<Node>>,
}

impl AVLTree {
    fn new() -> Self {
        AVLTree { root: None }
    }
    #[allow(unused)]
    fn len(&self) -> usize {
        Node::len(&self.root)
    }
    fn insert(&mut self, p: i64) {
        self.root = Node::insert(self.root.take(), Node::new(p));
    }
    fn at(&self, pos: usize) -> Option<i64> {
        Node::at(&self.root, pos)
    }
    fn acc(&self, pos: usize) -> i64 {
        Node::acc(&self.root, pos)
    }
    fn erase(&mut self, p: i64) {
        self.root = Node::erase(self.root.take(), p);
    }
    // The order is not specified.
    #[allow(unused)]
    fn each<F: FnMut(i64)>(&self, mut f: F) {
        Node::each(&self.root, &mut f)
    }
}

// Tags: balanced-binary-search-tree
fn main() {
    let n;
    let k;
    let mut a;
    if true {
        input! {
            n_: usize,
            k_: usize,
            a_: [i64; n_],
        }
        n = n_;
        k = k_;
        a = a_;
    } else {
        n = 100000;
        k = 50000;
        a = vec![0; n];
        for i in 0 .. n {
            a[i] = i as i64 + 1;
        }
    }
    let mut acc = vec![0; n + 1];
    for i in 0..n {
        acc[i + 1] = acc[i] + a[i];
    }
    let mut ms = AVLTree::new();
    for i in 0..k {
        ms.insert(a[i]);
    }
    const INF: i64 = 1 << 50;
    let mut mi = INF;
    for i in k..n + 1 {
        let mid = (k + 1) / 2;
        let med = ms.at(mid - 1).unwrap();
        let sum = ms.acc(mid);
        let tmp = sum * 2 - acc[i] + acc[i - k] + med * (k as i64 - mid as i64 * 2);
        // eprintln!("{} => {} (med = {}, sum = {})", i, tmp, med, sum);
        // ms.each(|x| eprint!(" {}", x));
        // eprintln!();
        mi = min(mi, tmp);
        if i < n {
            ms.erase(a[i - k]);
            ms.insert(a[i]);
        }
    }
    println!("{}", mi);
}
0