Codeforces1696D. Permutation Graph,静态区间最大最小值,ST表

从 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() {

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值