从 1 到 n 的路径一定要经过两个极值点,以此递归即可获得最优解。
需要支持的操作是求静态区间的最大/最小值,可以用 ST 表,现场把我四年前的博客翻译成 rust…
https://blog.csdn.net/m0_37809890/article/details/82585410
#[allow(unused_imports)]
use std::cmp::{min,max};
use std::io::{BufWriter, stdin, stdout, Write};
use std::iter;
use std::mem::swap;
#[derive(Default)]
struct Scanner {
buffer: Vec<String>
}
impl Scanner {
fn next<T: std::str::FromStr>(&mut self) -> T {
loop {
if let Some(token) = self.buffer.pop() {
return token.parse().ok().expect("Failed parse");
}
let mut input = String::new();
stdin().read_line(&mut input).expect("Failed read");
self.buffer = input.split_whitespace().rev().map(String::from).collect();
}
}
#[allow(dead_code)]
fn next_n<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
(0..n).map(|_| self.next::<T>()).collect()
}
}
struct STable {
max_table: Vec<Vec<i32>>,
min_table: Vec<Vec<i32>>,
lg: Vec<usize>,
}
impl STable {
fn new(n: usize, a: Vec<i32>) -> STable {
let mut st = STable {
max_table: vec![],
min_table: vec![],
lg: vec![],
};
st.lg = vec![0; n + 2];
st.lg[1] = 0;
for i in 2..=n+1 {
st.lg[i] = st.lg[i>>1] + 1;
}
st.max_table = vec![vec![0; n+1]; st.lg[n]+1];
for i in 1..=n {
st.max_table[0][i] = a[i];
}
for i in 1..=st.lg[n] {
for j in 1..=n {
if j+(1<<i)-1 <= n {
st.max_table[i][j] = st.max_table[i-1][j].max(st.max_table[i-1][j+(1<<(i-1))]);
}
}
}
st.min_table = vec![vec![0; n+1]; st.lg[n]+1];
for i in 1..=n {
st.min_table[0][i] = a[i];
}
for i in 1..=st.lg[n] {
for j in 1..=n {
if j+(1<<i)-1 <= n {
st.min_table[i][j] = st.min_table[i-1][j].min(st.min_table[i-1][j+(1<<(i-1))]);
}
}
}
st
}
fn query_max(&self, i: usize, j: usize) -> i32 {
let t = self.lg[j-i+1];
self.max_table[t][i].max(self.max_table[t][j-(1<<t)+1])
}
fn query_min(&self, i: usize, j: usize) -> i32 {
let t = self.lg[j-i+1];
self.min_table[t][i].min(self.min_table[t][j-(1<<t)+1])
}
}
fn work(n: usize, a: Vec<i32>) -> i32 {
// println!("n={:?}", n);
// println!("a={:?}", a);
let val_to_pos = {
let mut res = vec![0; n+1];
for i in 1..=n {
res[a[i] as usize] = i;
}
res
};
// println!("a={:?}", a);
// println!("vtp={:?}", val_to_pos);
let st = STable::new(n, a);
fn get_dis(from: usize, to: usize, st: &STable, vtp: &Vec<usize>) -> i32 {
if from == to {
return 0;
}
let mut pos1 = vtp[st.query_max(from, to) as usize];
let mut pos2 = vtp[st.query_min(from, to) as usize];
if pos1 > pos2 {
swap(&mut pos1, &mut pos2);
}
get_dis(from, pos1, st, vtp) + 1 + get_dis(pos2, to, st, vtp)
}
get_dis(1, n, &st, &val_to_pos)
}
fn main() {
let mut scanner = Scanner::default();
let out = &mut BufWriter::new(stdout());
let t = scanner.next::<usize>();
for _ in 0..t {
let n = scanner.next::<usize>();
let a = iter::once(0).chain(scanner.next_n::<i32>(n)).collect();
let res = work(n, a);
writeln!(out, "{}", res).ok();
}
}
#[test]
fn test() {
}