QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#221582 | #7616. Jump Graph | ucup-team635# | WA | 0ms | 2020kb | Rust | 10.0kb | 2023-10-21 13:52:13 | 2023-10-21 13:52:14 |
Judging History
answer
// 最大値に注目する
// そこから左に進む時の答え、右の答えを計算できたのなら
// 右側の項に左の答え+サイズを足し込む
// 左のこうも同様に
// なぜか?
// 左の項から初めて右の項にいくにはmaxを必ず経由する, また即maxに飛べるので、そう
//
// 左に進む時の答えというのは計算できるか?
// stackとかで極大なmaxを取る
// ある場所への最短路は左端、右端の小さい方
// みたいな計算になる
// よう考えるとこれはまた内側のmaxで切って、計算できそう
//
// 詰める
use std::io::Write;
use std::collections::*;
type Map<K, V> = BTreeMap<K, V>;
type Set<T> = BTreeSet<T>;
type Deque<T> = VecDeque<T>;
fn run() {
input! {
n: usize,
p: [usize1; n],
}
let mut ip = vec![0; n];
let mut seg = SegmentTreePURQ::new(n, 0, |a, b| std::cmp::max(*a, *b));
for (i, p) in p.iter().enumerate() {
ip[*p] = i;
seg.update_tmp(i, *p);
}
seg.update_all();
let memo = std::cell::RefCell::new(Map::new());
// opへ飛んでる時, [l, r) の最短路の和
let calc = recurse(|rec, (l, r, right): (usize, usize, bool)| -> usize {
if l >= r {
return 0;
}
if let Some(&d) = memo.borrow().get(&(l, r, right)) {
return d;
}
let mut ans = 0;
if right {
let mut pos = None;
let mut p = r;
while l < p {
let v = seg.find(l, p);
let x = ip[v];
ans += 1;// xへの最短路
if let Some(y) = pos {
if x + 1 < y {
ans += y - x - 1;
let m = seg.find(x + 1, y);
let z = ip[m];
ans += rec((x + 1, z + 1, true));
ans += rec((z, y, false));
ans -= 1;// z の重複
}
} else {
ans += r - x - 1;// 右へ飛ぶ分
ans += rec((x + 1, r, true));
}
pos = Some(x);
p = x;
}
} else {
let mut pos = None;
let mut p = l;
while p < r {
let v = seg.find(p, r);
let x = ip[v];
ans += 1;// xへの最短路
if let Some(y) = pos {
if y + 1 < x {
ans += x - y - 1;
let m = seg.find(y + 1, x);
let z = ip[m];
ans += rec((y + 1, z + 1, true));
ans += rec((z, x, false));
ans -= 1;// z の重複
}
} else {
ans += x - l;// 左へ飛ぶ分
ans += rec((l, x, false));
}
pos = Some(x);
p = x + 1;
}
}
memo.borrow_mut().insert((l, r, right), ans);
ans
});
let mut imos = vec![0; n + 1];
let mut dfs = vec![(0, n)];
while let Some((l, r)) = dfs.pop() {
if l >= r {
continue;
}
let v = seg.find(l, r);
let x = ip[v];
imos[x] += r - l - 1;
imos[x + 1] -= r - l - 1;
let p = calc((l, x, false));
let q = calc((x + 1, r, true));
imos[x + 1] += p + x - l + 1;
imos[r] -= p + x - l + 1;
imos[l] += q + r - x;
imos[x] -= q + r - x;
dfs.push((l, x));
dfs.push((x + 1, r));
}
for i in 1..n {
imos[i] += imos[i - 1];
}
imos.pop();
use util::*;
println!("{}", imos.iter().join(" "));
}
fn main() {
run();
}
// ---------- begin input macro ----------
// reference: https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
#[macro_export]
macro_rules! input {
(source = $s:expr, $($r:tt)*) => {
let mut iter = $s.split_whitespace();
input_inner!{iter, $($r)*}
};
($($r:tt)*) => {
let s = {
use std::io::Read;
let mut s = String::new();
std::io::stdin().read_to_string(&mut s).unwrap();
s
};
let mut iter = s.split_whitespace();
input_inner!{iter, $($r)*}
};
}
#[macro_export]
macro_rules! input_inner {
($iter:expr) => {};
($iter:expr, ) => {};
($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
let $var = read_value!($iter, $t);
input_inner!{$iter $($r)*}
};
}
#[macro_export]
macro_rules! read_value {
($iter:expr, ( $($t:tt),* )) => {
( $(read_value!($iter, $t)),* )
};
($iter:expr, [ $t:tt ; $len:expr ]) => {
(0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
};
($iter:expr, chars) => {
read_value!($iter, String).chars().collect::<Vec<char>>()
};
($iter:expr, bytes) => {
read_value!($iter, String).bytes().collect::<Vec<u8>>()
};
($iter:expr, usize1) => {
read_value!($iter, usize) - 1
};
($iter:expr, $t:ty) => {
$iter.next().unwrap().parse::<$t>().expect("Parse error")
};
}
// ---------- end input macro ----------
// ---------- begin segment tree Point Update Range Query ----------
pub struct SegmentTreePURQ<T, F> {
n: usize,
size: usize,
data: Vec<T>,
e: T,
op: F,
}
impl<T, F> SegmentTreePURQ<T, F>
where
T: Clone,
F: Fn(&T, &T) -> T,
{
pub fn new(n: usize, e: T, op: F) -> Self {
assert!(n > 0);
let size = n.next_power_of_two();
let data = vec![e.clone(); 2 * size];
SegmentTreePURQ {
n,
size,
data,
e,
op,
}
}
pub fn update_tmp(&mut self, x: usize, v: T) {
assert!(x < self.n);
self.data[x + self.size] = v;
}
pub fn update_all(&mut self) {
for i in (1..self.size).rev() {
self.data[i] = (self.op)(&self.data[2 * i], &self.data[2 * i + 1]);
}
}
pub fn update(&mut self, x: usize, v: T) {
assert!(x < self.n);
let mut x = x + self.size;
self.data[x] = v;
x >>= 1;
while x > 0 {
self.data[x] = (self.op)(&self.data[2 * x], &self.data[2 * x + 1]);
x >>= 1;
}
}
pub fn find(&self, l: usize, r: usize) -> T {
assert!(l <= r && r <= self.n);
if l == r {
return self.e.clone();
}
let mut l = self.size + l;
let mut r = self.size + r;
let mut x = self.e.clone();
let mut y = self.e.clone();
while l < r {
if l & 1 == 1 {
x = (self.op)(&x, &self.data[l]);
l += 1;
}
if r & 1 == 1 {
r -= 1;
y = (self.op)(&self.data[r], &y);
}
l >>= 1;
r >>= 1;
}
(self.op)(&x, &y)
}
pub fn max_right<P>(&self, l: usize, f: P) -> usize
where
P: Fn(&T) -> bool,
{
assert!(l <= self.n);
assert!(f(&self.e));
if l == self.n {
return self.n;
}
let mut l = l + self.size;
let mut sum = self.e.clone();
while {
l >>= l.trailing_zeros();
let v = (self.op)(&sum, &self.data[l]);
if !f(&v) {
while l < self.size {
l <<= 1;
let v = (self.op)(&sum, &self.data[l]);
if f(&v) {
sum = v;
l += 1;
}
}
return l - self.size;
}
sum = v;
l += 1;
l.count_ones() > 1
} {}
self.n
}
pub fn min_left<P>(&self, r: usize, f: P) -> usize
where
P: Fn(&T) -> bool,
{
assert!(r <= self.n);
assert!(f(&self.e));
if r == 0 {
return 0;
}
let mut r = r + self.size;
let mut sum = self.e.clone();
while {
r -= 1;
while r > 1 && r & 1 == 1 {
r >>= 1;
}
let v = (self.op)(&self.data[r], &sum);
if !f(&v) {
while r < self.size {
r = 2 * r + 1;
let v = (self.op)(&self.data[r], &sum);
if f(&v) {
sum = v;
r -= 1;
}
}
return r + 1 - self.size;
}
sum = v;
(r & (!r + 1)) != r
} {}
0
}
}
// ---------- end segment tree Point Update Range Query ----------
// ---------- begin recurse ----------
// reference
// https://twitter.com/noshi91/status/1393952665566994434
// https://twitter.com/shino16_cp/status/1393933468082397190
pub fn recurse<A, R, F>(f: F) -> impl Fn(A) -> R
where
F: Fn(&dyn Fn(A) -> R, A) -> R,
{
fn call<A, R, F>(f: &F, a: A) -> R
where
F: Fn(&dyn Fn(A) -> R, A) -> R,
{
f(&|a| call(f, a), a)
}
move |a| call(&f, a)
}
// ---------- end recurse ----------
mod util {
pub trait Join {
fn join(self, sep: &str) -> String;
}
impl<T, I> Join for I
where
I: Iterator<Item = T>,
T: std::fmt::Display,
{
fn join(self, sep: &str) -> String {
let mut s = String::new();
use std::fmt::*;
for (i, v) in self.enumerate() {
if i > 0 {
write!(&mut s, "{}", sep).ok();
}
write!(&mut s, "{}", v).ok();
}
s
}
}
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 0
Wrong Answer
time: 0ms
memory: 2020kb
input:
6 1 6 3 2 5 4
output:
11 5 7 7 6 8
result:
wrong answer 1st lines differ - expected: '11 7 7 7 6 8', found: '11 5 7 7 6 8'