use std::cmp;use std::time::SystemTime;
struct IndexTree { tree: Vec<i64>, n: i64,}
impl IndexTree { fn new(size: i64) -> IndexTree { let tree = vec![0; (size + 1) as usize]; let mut it = IndexTree { tree: tree, n: size, }; for i in 1..=size { it.add(i, 1); } it }
fn sum(&self, mut i: i64) -> i64 { let mut ret = 0; while i > 0 { ret += self.tree[i as usize]; i -= i & -i; } ret }
fn sum_range(&self, l: i64, r: i64) -> i64 { self.sum(r) - self.sum(l - 1) }
fn add(&mut self, mut i: i64, d: i64) { while i <= self.n { self.tree[i as usize] += d; i += i & -i; } }}
struct SegmentTree { n: i64, min: Vec<i64>,}
impl SegmentTree { fn new(arr: &[i64]) -> SegmentTree { let n = arr.len() as i64; let min = vec![0; ((n + 1) << 2) as usize]; let mut st = SegmentTree { n: n, min: min }; for i in 1..=n { st.update(i, arr[(i - 1) as usize]); } st }
fn update(&mut self, i: i64, v: i64) { self.update_segment(i, i, v, 1, self.n, 1); }
fn update_segment(&mut self, L: i64, R: i64, C: i64, l: i64, r: i64, rt: i64) { if L <= l && r <= R { self.min[rt as usize] = C; return; } let mid = (l + r) >> 1; if L <= mid { self.update_segment(L, R, C, l, mid, rt << 1); } if R > mid { self.update_segment(L, R, C, mid + 1, r, rt << 1 | 1); } self.push_up(rt); }
fn push_up(&mut self, rt: i64) { self.min[rt as usize] = cmp::min( self.min[(rt << 1) as usize], self.min[(rt << 1 | 1) as usize], ); }
fn min_query(&self, L: i64, R: i64, l: i64, r: i64, rt: i64) -> i64 { if L <= l && r <= R { return self.min[rt as usize]; } let mid = (l + r) >> 1; let mut ans = i64::MAX; if L <= mid { ans = cmp::min(ans, self.min_query(L, R, l, mid, rt << 1)); } if R > mid { ans = cmp::min(ans, self.min_query(L, R, mid + 1, r, rt << 1 | 1)); } ans }
fn min(&self, l: i64, r: i64) -> i64 { self.min_query(l, r, 1, self.n, 1) }}
fn days1(diamonds: &mut [i64]) -> i64 { let mut arr = diamonds.to_vec(); let mut ans = 0; while !arr.is_empty() { ans += 1; deal(&mut arr); } ans}
fn deal(arr: &mut Vec<i64>) { let head = arr.remove(0); let mut min0 = head; for a in arr.iter() { min0 = min0.min(*a); } if head > min0 { arr.push(head); }}
fn days2(diamonds: &[i64]) -> i64 { let n = diamonds.len() as i64; let mut it = IndexTree::new(n); let mut st = SegmentTree::new(diamonds); let mut days = 0; let mut find = 1; let mut start = 1; while it.sum_range(1, n) != 0 { find = find_min(&st, start, n); days += days_count(&it, start, find, n); it.add(find, -1); st.update(find, i64::MAX); start = find; } days}
fn find_min(st: &SegmentTree, start: i64, n: i64) -> i64 { let (mut l, mut r, mut min) = (n, 1, st.min(1, n)); if st.min(start, n) == min { l = start; r = n; } else { l = 1; r = start - 1; } let (mut m, mut ans) = (-1, -1); while l <= r { m = (l + r) >> 1; if st.min(l, m) == min { ans = m; r = m - 1; } else { l = m + 1; } } ans}
fn days_count(it: &IndexTree, start: i64, find: i64, n: i64) -> i64 { if start <= find { it.sum_range(start, find) } else { it.sum_range(start, n) + it.sum_range(1, find) }}
fn random_array(n: i64, v: i64) -> Vec<i64> { let mut arr = vec![0; n as usize]; for i in 0..n { arr[i as usize] = ((rand::random::<i64>() % v) + v) % v; } arr}
fn main() { let now = SystemTime::now();
println!("例子测试开始"); let arr = vec![3, 1, 4, 3, 1, 2]; println!("{}", days1(&mut arr.to_vec())); println!("{}", days2(&arr)); println!("例子测试结束");
let n = 100; let v = 100000; let test_times = 1000; println!("随机测试开始"); for _ in 0..test_times { let n = ((rand::random::<i64>() % n) + n) % n + 1; let diamonds = random_array(n, v); let ans1 = days1(&mut diamonds.clone()); let ans2 = days2(&diamonds); if ans1 != ans2 { println!("出错了!"); } } println!("随机测试结束");
println!("性能测试开始"); let n = 100000; let v = 1000000000; let diamonds = random_array(n, v); println!("宝石数量 : {}", n); println!("价值范围 : {}", v); let start = SystemTime::now(); days2(&diamonds); let end = SystemTime::now(); println!( "运行时间 : {} 毫秒", end.duration_since(start).unwrap().as_millis() );
println!("性能测试结束");}
评论