017 - Crossing Segments(★7) Editorial by ngtkana
ウェーブレット行列を用いた解法をご紹介します。
入力が \(R _ i\) に関してソート済みであるとして良いです。さらに数列 \(L = (L _ i) _ { i = 1 } ^ N\) に対応するウェーブレット行列 \(W\) を構築しておきます。 線分同士が相異なりかつ交差する条件は \(L _ i \lt L _ j \lt R _ i \lt R _ j\) です。\(j\) を固定すると
- \(L _ i \lt L _ j\)
- \(\mathop { \mathtt { upper\_bound }} ( R, L _ j ) \le i \lt \mathop { \mathtt { lower\_bound }} ( R, R _ j ) \)
と言い換えられますから、ウェーブレット行列 \(W\) の \(\mathop { \mathtt { range\_freq } }\) を用いて、\(L\) の要素であって添字が\(\lbrack \mathop { \mathtt { upper\_bound }} ( R, L _ j ), \mathop { \mathtt { lower\_bound }} ( R, R _ j ) \lbrack\)、値が \(\rbrack -\infty, L _ j \lbrack\) に含まれているものの個数を計算すればよいです。
use itertools::Itertools;
use proconio::{fastout, input, marker::Usize1};
use superslice::Ext;
use wavelet_matrix::WaveletMatrix;
#[fastout]
fn main() {
input! {
_total: usize,
n: usize,
start_end: [(Usize1, Usize1); n],
}
let ends = start_end.iter().map(|&(_, end)| end).sorted().collect_vec();
let wm = start_end
.iter()
.sorted_by_key(|&(_, end)| end)
.map(|&(start, _)| start)
.collect::<WaveletMatrix>();
let ans = start_end
.iter()
.map(|&(start, end)| {
let l = ends.upper_bound(&start);
let r = ends.lower_bound(&end);
wm.range_freq(l..r, ..start)
})
.sum::<usize>();
println!("{}", ans);
}
mod wavelet_matrix {
/* 省略 */
}
提出 (549 ms): https://atcoder.jp/contests/typical90/submissions/28306990
posted:
last update: