QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#378280#8572. Passing Gameucup-team635#TL 0ms2200kbRust4.5kb2024-04-06 10:44:492024-04-06 10:44:50

Judging History

你现在查看的是最新测评结果

  • [2024-04-06 10:44:50]
  • 评测
  • 测评结果:TL
  • 用时:0ms
  • 内存:2200kb
  • [2024-04-06 10:44:49]
  • 提交

answer

// ---------- begin Li Chao Tree ----------
// verify: https://old.yosupo.jp/submission/66738
#[derive(Clone)]
pub struct Line {
    a: i64,
    b: i64,
}

impl Line {
    pub fn new(a: i64, b: i64) -> Self {
        Line { a, b }
    }
    pub fn eval(&self, x: i64) -> i64 {
        self.a * x + self.b
    }
}

pub struct LiChaoTree(Vec<(i64, Line)>);

impl LiChaoTree {
    fn inorder(&mut self, v: usize, point: &[i64], x: &mut usize) {
        if v >= self.0.len() {
            return;
        }
        self.inorder(2 * v + 1, point, x);
        self.0[v].0 = point[*x];
        *x += 1;
        self.inorder(2 * v + 2, point, x);
    }
    pub fn new(mut point: Vec<i64>) -> Self {
        assert!(point.len() > 0);
        point.sort();
        point.dedup();
        let mut cht = Self(vec![(0, Line::new(0, std::i64::MAX)); point.len()]);
        cht.inorder(0, &point, &mut 0);
        cht
    }
    pub fn insert(&mut self, mut line: Line) {
        let mut v = 0;
        while let Some(p) = self.0.get_mut(v) {
            if p.1.eval(p.0) > line.eval(p.0) {
                std::mem::swap(&mut p.1, &mut line);
            }
            v = 2 * v + if line.a > p.1.a { 1 } else { 2 };
        }
    }
    pub fn find(&self, x: i64) -> i64 {
        let mut res = std::i64::MAX;
        let mut v = 0;
        while let Some(p) = self.0.get(v) {
            res = res.min(p.1.eval(x));
            v = 2 * v + if x < p.0 { 1 } else { 2 }
        }
        res
    }
}
// ---------- end Li Chao Tree ----------
// ---------- begin scannner ----------
#[allow(dead_code)]
mod scanner {
    use std::str::FromStr;
    pub struct Scanner<'a> {
        it: std::str::SplitWhitespace<'a>,
    }
    impl<'a> Scanner<'a> {
        pub fn new(s: &'a String) -> Scanner<'a> {
            Scanner {
                it: s.split_whitespace(),
            }
        }
        pub fn next<T: FromStr>(&mut self) -> T {
            self.it.next().unwrap().parse::<T>().ok().unwrap()
        }
        pub fn next_bytes(&mut self) -> Vec<u8> {
            self.it.next().unwrap().bytes().collect()
        }
        pub fn next_chars(&mut self) -> Vec<char> {
            self.it.next().unwrap().chars().collect()
        }
        pub fn next_vec<T: FromStr>(&mut self, len: usize) -> Vec<T> {
            (0..len).map(|_| self.next()).collect()
        }
    }
}
// ---------- end scannner ----------

use std::io::Write;
use std::collections::*;

type Map<K, V> = BTreeMap<K, V>;
type Set<T> = BTreeSet<T>;
type Deque<T> = VecDeque<T>;

fn main() {
    use std::io::Read;
    let mut s = String::new();
    std::io::stdin().read_to_string(&mut s).unwrap();
    let mut sc = scanner::Scanner::new(&s);
    let out = std::io::stdout();
    let mut out = std::io::BufWriter::new(out.lock());
    run(&mut sc, &mut out);
}

fn run<W: Write>(sc: &mut scanner::Scanner, out: &mut std::io::BufWriter<W>) {
    let t: u32 = sc.next();
    for _ in 0..t {
        let n: usize = sc.next();
        let k: usize = sc.next();
        let x: Vec<i64> = sc.next_vec::<i64>(n);
        let s: Vec<i64> = sc.next_vec::<i64>(n);
        let ans = solve(k, x, s);
        writeln!(out, "{}", ans).ok();
    }
}

fn solve(k: usize, x: Vec<i64>, s: Vec<i64>) -> i64 {
    let n = x.len();
    let mut ord = (0..n).collect::<Vec<_>>();
    ord.sort_by_key(|p| x[*p]);
    let e = ord.iter().map(|e| (x[*e], s[*e])).collect::<Vec<_>>();
    let src = ord.iter().position(|x| *x == 0).unwrap();
    let dst = ord.iter().position(|x| *x == n - 1).unwrap();
    let mut ans = std::i64::MAX;
    for i in 0..2 {
        let inf = std::i64::MAX / 2;
        let mut dp = vec![inf; n];
        dp[src] = 0;
        let point = e.iter().map(|e| e.0).collect::<Vec<_>>();
        for j in 0..=k.min(30) {
            let mut cht = LiChaoTree::new(point.clone());
            if (i + j) % 2 == 0 {
                for (i, &(x, s)) in e.iter().enumerate() {
                    dp[i] = dp[i].min(cht.find(x));
                    if dp[i] != inf {
                        cht.insert(Line::new(s, dp[i] - s * x));
                    }
                }
            } else {
                for (i, &(x, s)) in e.iter().enumerate().rev() {
                    dp[i] = dp[i].min(cht.find(-x));
                    if dp[i] != inf {
                        cht.insert(Line::new(s, dp[i] + s * x));
                    }
                }
            }
        }
        ans = ans.min(dp[dst]);
    }
    ans
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 2200kb

input:

2
4 2
3 2 1 6
3 1 1 3
2 0
1 2
1 2

output:

7
1

result:

ok 2 number(s): "7 1"

Test #2:

score: -100
Time Limit Exceeded

input:

1
300000 204334
809492393 304618667 173130445 377106790 364888630 949045125 622060683 557772818 216607577 848817467 862855568 507840723 120816645 639713488 741781998 682531787 685261161 601686403 355792373 162819930 710057718 234560726 998604853 678957602 485413982 855985802 109303681 979706626 4822...

output:


result: