use std::cmp::max; use std::io::{self, BufRead}; struct SegmentTree { size: usize, array: Vec, } impl SegmentTree { fn new(init_array: Vec) -> SegmentTree { let mut n = 1; while n < init_array.len() { n *= 2; } let mut array = vec![-1; 2 * n]; for (i, &a) in init_array.iter().enumerate() { array[n + i] = a; } let mut end_index = n; let mut start_index = end_index / 2; while start_index >= 1 { for i in start_index..end_index { array[i] = max(array[2 * i], array[2 * i + 1]); } end_index = start_index; start_index /= 2; } SegmentTree { size: n, array } } fn set(&mut self, x: usize, a: i32) { let mut index = self.size + x; self.array[index] = a; while index > 1 { index /= 2; self.array[index] = max(self.array[2 * index], self.array[2 * index + 1]); } } fn get_max(&self, l: usize, r: usize) -> i32 { let mut L = self.size + l; let mut R = self.size + r; let mut s = -1; while L < R { if R & 1 == 1 { R -= 1; s = max(s, self.array[R]); } if L & 1 == 1 { s = max(s, self.array[L]); L += 1; } L >>= 1; R >>= 1; } s } } fn main() { let stdin = io::stdin(); let mut lines = stdin.lock().lines(); let first_line = lines.next().unwrap().unwrap(); let mut parts = first_line.split_whitespace(); let N: usize = parts.next().unwrap().parse().unwrap(); let Q: usize = parts.next().unwrap().parse().unwrap(); let second_line = lines.next().unwrap().unwrap(); let A: Vec = second_line .split_whitespace() .map(|x| x.parse().unwrap()) .collect(); let mut queries = Vec::new(); for _ in 0..Q { let query_line = lines.next().unwrap().unwrap(); let mut query_parts = query_line.split_whitespace(); query_parts.next(); // skip the first number let l: usize = query_parts.next().unwrap().parse().unwrap(); let r: usize = query_parts.next().unwrap().parse().unwrap(); queries.push((l - 1, r - 1)); } let mut seg_tree = SegmentTree::new(vec![-1; N + 1]); let mut max_left_list = vec![-1; N]; for i in 0..N { let a = A[i]; let ans = seg_tree.get_max((a + 1) as usize, N + 1); max_left_list[i] = ans; seg_tree.set(a as usize, i as i32); } let sqrt_n = (N as f64).sqrt() as usize; let mut partitions = Vec::new(); let mut left = 0; while left < N { partitions.push((left, std::cmp::min(N, left + sqrt_n))); left += sqrt_n; } let mut partitions_array = Vec::new(); for &(l, r) in &partitions { let mut cum_array = vec![0; N + 1]; for j in l..r { let a = A[j]; let l_index = max_left_list[j]; cum_array[(l_index + 1) as usize] += 1; } let mut cum_a = 0; for n in 0..=N { cum_a += cum_array[n]; cum_array[n] = cum_a; } partitions_array.push(cum_array); } for &(l, r) in &queries { let mut left_i = -1; let mut right_i = -1; for i in 0..partitions.len() { if l < partitions[i].1 { left_i = i as i32; } if r < partitions[i].1 { right_i = i as i32; } } let mut answer = 0; if (right_i - left_i).abs() <= 1 { for i in l..=r { if l as i32 > max_left_list[i] as i32 { answer += 1; } } } else { for i in l..partitions[left_i as usize].1 { if l as i32 > max_left_list[i] as i32 { answer += 1; } } for i in partitions[right_i as usize].0..=r { if l as i32 > max_left_list[i] as i32 { answer += 1; } } for i in (left_i + 1) as usize..right_i as usize { let a = partitions_array[i][l + 1]; answer += partitions_array[i][1] - partitions_array[i][0] - a; } } println!("{}", answer); } }