結果
問題 |
No.1300 Sum of Inversions
|
ユーザー |
![]() |
提出日時 | 2025-09-04 19:44:28 |
言語 | Rust (1.83.0 + proconio) |
結果 |
WA
|
実行時間 | - |
コード長 | 10,089 bytes |
コンパイル時間 | 14,502 ms |
コンパイル使用メモリ | 400,504 KB |
実行使用メモリ | 33,920 KB |
最終ジャッジ日時 | 2025-09-04 19:44:53 |
合計ジャッジ時間 | 20,672 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 33 WA * 1 |
ソースコード
use std::collections::BTreeMap; use bit::BinaryIndexedTree; use modint::ModInt998244353; use proconio::input; type Mint = ModInt998244353; fn main() { input! { n: usize, a: [i64; n], } let mut by_value = BTreeMap::new(); let mut bit_small_cnt = BinaryIndexedTree::new(n, 0); let mut bit_small_sum = BinaryIndexedTree::new(n, 0); let mut bit_large_cnt = BinaryIndexedTree::new(n, 0); let mut bit_large_sum = BinaryIndexedTree::new(n, 0); for (i, &a) in a.iter().enumerate() { by_value.entry(a).or_insert(vec![]).push(i); bit_large_cnt.add(i, 1); bit_large_sum.add(i, a); } let mut ans = Mint::new(0); for (&a, v) in &by_value { for &i in v { bit_large_cnt.add(i, -1); bit_large_sum.add(i, -a); } for &i in v { let small_cnt = bit_small_cnt.sum(i, n); let small_sum = bit_small_sum.sum(i, n); let large_cnt = bit_large_cnt.sum(0, i); let large_sum = bit_large_sum.sum(0, i); ans += small_sum * large_cnt; ans += large_sum * small_cnt; ans += Mint::new(a as u64) * small_cnt * large_cnt; } for &i in v { bit_small_cnt.add(i, 1); bit_small_sum.add(i, a); } } println!("{ans}"); } #[allow(dead_code)] mod bit { pub struct BinaryIndexedTree<T> { n: usize, array: Vec<T>, e: T, } impl<T> BinaryIndexedTree<T> where T: Clone + std::ops::AddAssign + std::ops::Sub<Output = T> + std::cmp::PartialOrd, { pub fn new(n: usize, e: T) -> Self { Self { n, array: vec![e.clone(); n + 1], e, } } pub fn add(&mut self, i: usize, x: T) { let mut i = i + 1; while i <= self.n { self.array[i] += x.clone(); i += i & i.wrapping_neg(); } } pub fn cum(&self, mut i: usize) -> T { let mut cum = self.e.clone(); while i > 0 { cum += self.array[i].clone(); i -= i & i.wrapping_neg(); } cum } pub fn sum(&self, l: usize, r: usize) -> T { self.cum(r) - self.cum(l) } pub fn lower_bound(&self, mut x: T) -> usize { let mut i = 0; let mut k = 1 << (self.n.next_power_of_two().trailing_zeros()); while k > 0 { if i + k <= self.n && self.array[i + k] < x { x = x - self.array[i + k].clone(); i += k; } k >>= 1; } i } } } #[allow(dead_code)] mod modint { use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; pub type ModInt998244353 = ModInt<998244353>; pub type ModInt1000000007 = ModInt<1000000007>; type ModIntInner = u64; #[derive(Clone, Copy, PartialEq, Eq)] pub struct ModInt<const M: ModIntInner> { val: ModIntInner, } impl<const M: ModIntInner> ModInt<M> { const IS_PRIME: bool = is_prime(M as u32); pub const fn modulus() -> ModIntInner { M } pub const fn new(val: ModIntInner) -> Self { assert!(M < (1 << 31)); Self { val: val.rem_euclid(M), } } pub const fn new_unchecked(val: ModIntInner) -> Self { Self { val } } pub const fn val(&self) -> ModIntInner { self.val } pub fn pow(self, mut exp: u64) -> Self { let mut result = Self::new(1); let mut base = self; while exp > 0 { if exp & 1 == 1 { result *= base; } base *= base; exp >>= 1; } result } pub fn inv(self) -> Self { assert!(Self::IS_PRIME); self.pow(M as u64 - 2).into() } } impl<const M: ModIntInner> std::fmt::Display for ModInt<M> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.val) } } impl<const M: ModIntInner> std::fmt::Debug for ModInt<M> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.val) } } impl<const M: ModIntInner> std::str::FromStr for ModInt<M> { type Err = std::num::ParseIntError; fn from_str(s: &str) -> Result<Self, Self::Err> { let value = s.parse::<ModIntInner>()?; Ok(ModInt::new(value)) } } impl<const M: ModIntInner> Neg for ModInt<M> { type Output = Self; fn neg(mut self) -> Self::Output { if self.val > 0 { self.val = M - self.val; } self } } impl<const M: ModIntInner, T: Into<ModInt<M>>> AddAssign<T> for ModInt<M> { fn add_assign(&mut self, rhs: T) { self.val += rhs.into().val; if self.val >= M { self.val -= M; } } } impl<const M: ModIntInner, T: Into<ModInt<M>>> SubAssign<T> for ModInt<M> { fn sub_assign(&mut self, rhs: T) { self.val = self.val.wrapping_sub(rhs.into().val); if self.val > M { self.val = self.val.wrapping_add(M); } } } impl<const M: ModIntInner, T: Into<ModInt<M>>> MulAssign<T> for ModInt<M> { fn mul_assign(&mut self, rhs: T) { self.val = self.val * rhs.into().val % M; } } impl<const M: ModIntInner, T: Into<ModInt<M>>> DivAssign<T> for ModInt<M> { fn div_assign(&mut self, rhs: T) { *self *= rhs.into().inv(); } } macro_rules! impl_binnary_operators { ($({ $op: ident, $op_assign: ident, $fn: ident, $fn_assign: ident}),*) => {$( impl<const M: ModIntInner, T: Into<ModInt<M>>> $op<T> for ModInt<M> { type Output = ModInt<M>; fn $fn(mut self, rhs: T) -> ModInt<M> { self.$fn_assign(rhs.into()); self } } impl<const M: ModIntInner> $op<&ModInt<M>> for ModInt<M> { type Output = ModInt<M>; fn $fn(self, rhs: &ModInt<M>) -> ModInt<M> { self.$fn(*rhs) } } impl<const M: ModIntInner, T: Into<ModInt<M>>> $op<T> for &ModInt<M> { type Output = ModInt<M>; fn $fn(self, rhs: T) -> ModInt<M> { (*self).$fn(rhs.into()) } } impl<const M: ModIntInner> $op<&ModInt<M>> for &ModInt<M> { type Output = ModInt<M>; fn $fn(self, rhs: &ModInt<M>) -> ModInt<M> { (*self).$fn(*rhs) } } impl<const M: ModIntInner> $op_assign<&ModInt<M>> for ModInt<M> { fn $fn_assign(&mut self, rhs: &ModInt<M>) { *self = self.$fn(*rhs); } } )*}; } impl_binnary_operators!( {Add, AddAssign, add, add_assign}, {Sub, SubAssign, sub, sub_assign}, {Mul, MulAssign, mul, mul_assign}, {Div, DivAssign, div, div_assign} ); impl<const M: ModIntInner> std::iter::Sum for ModInt<M> { fn sum<I: Iterator<Item = Self>>(iter: I) -> Self { iter.fold(Self::new(0), Add::add) } } impl<'a, const M: ModIntInner> std::iter::Sum<&'a Self> for ModInt<M> { fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self { iter.fold(Self::new(0), Add::add) } } impl<const M: ModIntInner> std::iter::Product for ModInt<M> { fn product<I: Iterator<Item = Self>>(iter: I) -> Self { iter.fold(Self::new(1), Mul::mul) } } impl<'a, const M: ModIntInner> std::iter::Product<&'a Self> for ModInt<M> { fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self { iter.fold(Self::new(1), Mul::mul) } } macro_rules! impl_rem_euclid_signed { ($($ty:tt),*) => { $( impl<const M: ModIntInner> From<$ty> for ModInt<M> { fn from(value: $ty) -> ModInt<M> { Self::new_unchecked((value as i64).rem_euclid(M as i64) as ModIntInner) } } )* }; } impl_rem_euclid_signed!(i8, i16, i32, i64, isize); macro_rules! impl_rem_euclid_unsigned { ($($ty:tt),*) => { $( impl<const M: ModIntInner> From<$ty> for ModInt<M> { fn from(value: $ty) -> ModInt<M> { Self::new_unchecked((value as u64).rem_euclid(M as u64) as ModIntInner) } } )* }; } impl_rem_euclid_unsigned!(u8, u16, u32, u64, usize); const fn is_prime(n: u32) -> bool { const fn miller_rabin(n: u32, witness: u32) -> bool { let (n, witness) = (n as u64, witness as u64); let mut d = n >> (n - 1).trailing_zeros(); let mut y = { let (mut res, mut pow, mut e) = (1, witness, d); while e > 0 { if e & 1 == 1 { res = res * pow % n; } pow = pow * pow % n; e >>= 1; } res }; while d != n - 1 && y != 1 && y != n - 1 { y = y * y % n; d <<= 1; } y == n - 1 || d & 1 == 1 } const WITNESS: [u32; 3] = [2, 7, 61]; if n == 1 || n % 2 == 0 { return n == 2; } let mut i = 0; while i < WITNESS.len() { if !miller_rabin(n, WITNESS[i]) { return false; } i += 1; } true } }