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!("性能测试结束");
}
评论