結果
| 問題 | No.121 傾向と対策:門松列(その2) |
| コンテスト | |
| ユーザー |
norioc
|
| 提出日時 | 2026-01-30 21:08:40 |
| 言語 | Rust (1.93.0 + proconio + num + itertools) |
| 結果 |
AC
|
| 実行時間 | 1,039 ms / 5,000 ms |
| コード長 | 3,632 bytes |
| 記録 | |
| コンパイル時間 | 1,923 ms |
| コンパイル使用メモリ | 234,232 KB |
| 実行使用メモリ | 93,296 KB |
| 最終ジャッジ日時 | 2026-01-30 21:08:47 |
| 合計ジャッジ時間 | 6,408 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 9 |
コンパイルメッセージ
warning: unused import: `std::collections::HashSet`
--> src/main.rs:3:5
|
3 | use std::collections::HashSet;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default
warning: unused imports: `marker::Chars` and `marker::Usize1`
--> src/main.rs:6:23
|
6 | use proconio::{input, marker::Usize1, marker::Chars};
| ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
warning: field `vs` is never read
--> src/main.rs:68:5
|
67 | struct Compression<T> {
| ----------- field in this struct
68 | vs: Vec<T>, // ソート済み・重複なしの値
| ^^
|
= note: `Compression` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
= note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default
warning: methods `len`, `value`, and `map` are never used
--> src/main.rs:93:8
|
72 | / impl<T> Compression<T>
73 | | where
74 | | T: Ord + Copy + Eq + Hash,
| |______________________________- methods in this implementation
...
93 | fn len(&self) -> usize {
| ^^^
...
103 | fn value(&self, index: usize) -> T {
| ^^^^^
...
108 | fn map<I>(&self, iterable: I) -> Vec<usize>
| ^^^
ソースコード
#![allow(non_snake_case)]
use std::collections::HashSet;
use std::collections::HashMap;
use std::hash::Hash;
use proconio::{input, marker::Usize1, marker::Chars};
use itertools::Itertools;
const INF: i64 = 1 << 62;
#[derive(Debug, Clone)]
struct FenwickTree {
n: usize,
data: Vec<i64>,
}
impl FenwickTree {
/// サイズ n の Fenwick Tree を作成
fn new(n: usize) -> Self {
let size = n + 10;
FenwickTree {
n: size,
data: vec![0; size],
}
}
/// p 番目に x を加算 (0-indexed)
fn add(&mut self, mut p: usize, x: i64) {
assert!(p < self.n);
p += 1;
while p < self.data.len() {
self.data[p] += x;
p += p & (!p + 1); // p & -p
}
}
/// 区間 [0, p] の和 (0-indexed)
fn sum(&self, mut p: usize) -> i64 {
assert!(p < self.n);
p += 1;
let mut s = 0;
while p > 0 {
s += self.data[p];
p &= p - 1; // p -= p & -p
}
s
}
/// 区間 [l, r] の和
fn range_sum(&self, l: usize, r: usize) -> i64 {
assert!(l <= r && r < self.n);
if l == 0 {
self.sum(r)
} else {
self.sum(r) - self.sum(l - 1)
}
}
/// p 番目の値
fn get(&self, p: usize) -> i64 {
self.range_sum(p, p)
}
}
#[derive(Debug)]
struct Compression<T> {
vs: Vec<T>, // ソート済み・重複なしの値
v2i: HashMap<T, usize>, // 値 -> インデックス
}
impl<T> Compression<T>
where
T: Ord + Copy + Eq + Hash,
{
/// iterable から座標圧縮を構築
fn new<I>(iterable: I) -> Self
where
I: IntoIterator<Item = T>,
{
let mut vs: Vec<T> = iterable.into_iter().collect();
vs.sort();
vs.dedup();
let mut v2i = HashMap::new();
for (i, &val) in vs.iter().enumerate() {
v2i.insert(val, i);
}
Self { vs, v2i }
}
fn len(&self) -> usize {
self.vs.len()
}
/// val のインデックスを返す
fn index(&self, val: T) -> usize {
self.v2i[&val]
}
/// インデックスに対応する値を返す
fn value(&self, index: usize) -> T {
self.vs[index]
}
/// iterable を圧縮後のインデックス列に変換
fn map<I>(&self, iterable: I) -> Vec<usize>
where
I: IntoIterator<Item = T>,
{
iterable.into_iter().map(|x| self.index(x)).collect()
}
}
fn main() {
input! {
N: usize,
A: [i64; N],
}
let comp = Compression::new(A.iter().chain([-INF, INF].iter()));
let xs = A.iter().map(|x| comp.index(x)).collect_vec();
let sz = xs.len();
let mut lt = FenwickTree::new(sz+10);
let mut rt = FenwickTree::new(sz+10);
let mut dup = FenwickTree::new(sz+10); // dup.get(x) : x の重複数
for &x in &xs {
rt.add(x, 1);
}
let mut ans = 0;
for x in xs { // 真ん中を x で固定
// 真ん中を最小値とする
let l = lt.range_sum(x+1, sz+5);
let r = rt.range_sum(x+1, sz+5);
ans += l * r; // 重複が含まれる
ans -= dup.range_sum(x+1, sz+5); // 重複を除く
// 真ん中を最大値とする
let l = lt.sum(x-1);
let r = rt.sum(x-1);
ans += l * r; // 重複が含まれる
ans -= dup.sum(x-1); // 重複を除く
lt.add(x, 1);
rt.add(x, -1);
let old = dup.get(x);
dup.add(x, lt.get(x) * rt.get(x) - old);
}
println!("{}", ans);
}
norioc