結果
問題 | No.1288 yuki collection |
ユーザー | fukafukatani |
提出日時 | 2021-01-03 22:39:29 |
言語 | Rust (1.77.0 + proconio) |
結果 |
TLE
(最新)
AC
(最初)
|
実行時間 | - |
コード長 | 10,993 bytes |
コンパイル時間 | 13,840 ms |
コンパイル使用メモリ | 384,256 KB |
実行使用メモリ | 84,336 KB |
最終ジャッジ日時 | 2024-10-13 16:23:29 |
合計ジャッジ時間 | 53,263 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 0 ms
5,248 KB |
testcase_01 | AC | 1 ms
5,248 KB |
testcase_02 | AC | 1 ms
5,248 KB |
testcase_03 | AC | 1 ms
5,248 KB |
testcase_04 | AC | 1 ms
5,248 KB |
testcase_05 | AC | 1 ms
5,248 KB |
testcase_06 | AC | 1 ms
5,248 KB |
testcase_07 | AC | 1 ms
5,248 KB |
testcase_08 | AC | 2 ms
5,248 KB |
testcase_09 | AC | 1 ms
5,248 KB |
testcase_10 | AC | 1 ms
5,248 KB |
testcase_11 | AC | 1 ms
5,248 KB |
testcase_12 | AC | 1 ms
5,248 KB |
testcase_13 | AC | 1,108 ms
39,424 KB |
testcase_14 | AC | 1,154 ms
39,040 KB |
testcase_15 | AC | 737 ms
32,640 KB |
testcase_16 | AC | 779 ms
32,768 KB |
testcase_17 | AC | 1,180 ms
39,424 KB |
testcase_18 | AC | 1,181 ms
39,296 KB |
testcase_19 | AC | 1,106 ms
39,040 KB |
testcase_20 | AC | 1,354 ms
40,192 KB |
testcase_21 | AC | 3,086 ms
55,040 KB |
testcase_22 | AC | 2,983 ms
54,876 KB |
testcase_23 | AC | 2,956 ms
54,244 KB |
testcase_24 | AC | 1,160 ms
39,808 KB |
testcase_25 | AC | 1,162 ms
39,936 KB |
testcase_26 | AC | 1,246 ms
39,680 KB |
testcase_27 | AC | 345 ms
22,656 KB |
testcase_28 | AC | 540 ms
31,872 KB |
testcase_29 | AC | 477 ms
34,816 KB |
testcase_30 | AC | 68 ms
36,992 KB |
testcase_31 | AC | 92 ms
38,272 KB |
testcase_32 | AC | 97 ms
37,120 KB |
testcase_33 | AC | 2,964 ms
62,848 KB |
testcase_34 | AC | 1,346 ms
41,088 KB |
testcase_35 | AC | 1,171 ms
39,296 KB |
testcase_36 | AC | 1,690 ms
45,056 KB |
testcase_37 | AC | 1,739 ms
45,312 KB |
testcase_38 | TLE | - |
testcase_39 | AC | 489 ms
63,592 KB |
testcase_40 | AC | 37 ms
37,568 KB |
testcase_41 | AC | 1 ms
6,820 KB |
testcase_42 | AC | 1 ms
6,816 KB |
ソースコード
#![allow(unused_imports)] use std::cmp::*; use std::collections::*; use std::io::Write; use std::ops::Bound::*; #[allow(unused_macros)] macro_rules! debug { ($($e:expr),*) => { #[cfg(debug_assertions)] $({ let (e, mut err) = (stringify!($e), std::io::stderr()); writeln!(err, "{} = {:?}", e, $e).unwrap() })* }; } fn main() { let n = read::<usize>(); let s = read::<String>(); let v = read_vec::<i64>(); let mut poses = vec![vec![]; 4]; for (i, ch) in s.chars().enumerate() { match ch { 'y' => poses[0].push(i), 'u' => poses[1].push(i), 'k' => poses[2].push(i), _ => poses[3].push(i), } } let mut flow = MinCostFlowGraph::new(2 * n + 2); for i in 0..n { flow.add_edge(2 * i, 2 * i + 1, 1, 0); } for &pos in &poses[0] { flow.add_edge(2 * n, 2 * pos, 1, 0); } let inf: i64 = 1000000000; for ci in 0..3 { for i in 0..poses[ci].len() { let pi = poses[ci][i]; for j in 0..poses[ci + 1].len() { let pj = poses[ci + 1][j]; if pj < pi { continue; } flow.add_edge(2 * pi + 1, 2 * pj, 1, inf - v[pi]); } } } for &pos in &poses[3] { flow.add_edge(2 * pos + 1, 2 * n + 1, 1, inf - v[pos]); } flow.add_edge(2 * n, 2 * n + 1, n as i64 / 4, inf * 4); let (cap, cost) = flow.flow(2 * n, 2 * n + 1, n as i64 / 4); // debug!((cap, cost)); let ans = inf * cap * 4 - cost; println!("{}", ans); } fn read<T: std::str::FromStr>() -> T { let mut s = String::new(); std::io::stdin().read_line(&mut s).ok(); s.trim().parse().ok().unwrap() } fn read_vec<T: std::str::FromStr>() -> Vec<T> { read::<String>() .split_whitespace() .map(|e| e.parse().ok().unwrap()) .collect() } //https://github.com/rust-lang-ja/ac-library-rs pub mod internal_type_traits { use std::{ fmt, iter::{Product, Sum}, ops::{ Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign, }, }; // Skipped: // // - `is_signed_int_t<T>` (probably won't be used directly in `modint.rs`) // - `is_unsigned_int_t<T>` (probably won't be used directly in `modint.rs`) // - `to_unsigned_t<T>` (not used in `fenwicktree.rs`) /// Corresponds to `std::is_integral` in C++. // We will remove unnecessary bounds later. // // Maybe we should rename this to `PrimitiveInteger` or something, as it probably won't be used in the // same way as the original ACL. pub trait Integral: 'static + Send + Sync + Copy + Ord + Not<Output = Self> + Add<Output = Self> + Sub<Output = Self> + Mul<Output = Self> + Div<Output = Self> + Rem<Output = Self> + AddAssign + SubAssign + MulAssign + DivAssign + RemAssign + Sum + Product + BitOr<Output = Self> + BitAnd<Output = Self> + BitXor<Output = Self> + BitOrAssign + BitAndAssign + BitXorAssign + Shl<Output = Self> + Shr<Output = Self> + ShlAssign + ShrAssign + fmt::Display + fmt::Debug + fmt::Binary + fmt::Octal + Zero + One + BoundedBelow + BoundedAbove { } /// Class that has additive identity element pub trait Zero { /// The additive identity element fn zero() -> Self; } /// Class that has multiplicative identity element pub trait One { /// The multiplicative identity element fn one() -> Self; } pub trait BoundedBelow { fn min_value() -> Self; } pub trait BoundedAbove { fn max_value() -> Self; } macro_rules! impl_integral { ($($ty:ty),*) => { $( impl Zero for $ty { #[inline] fn zero() -> Self { 0 } } impl One for $ty { #[inline] fn one() -> Self { 1 } } impl BoundedBelow for $ty { #[inline] fn min_value() -> Self { Self::min_value() } } impl BoundedAbove for $ty { #[inline] fn max_value() -> Self { Self::max_value() } } impl Integral for $ty {} )* }; } impl_integral!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize); } pub mod mincostflow { use crate::internal_type_traits::Integral; pub struct MinCostFlowEdge<T> { pub from: usize, pub to: usize, pub cap: T, pub flow: T, pub cost: T, } pub struct MinCostFlowGraph<T> { pos: Vec<(usize, usize)>, g: Vec<Vec<_Edge<T>>>, cost_sum: T, } impl<T> MinCostFlowGraph<T> where T: Integral + std::ops::Neg<Output = T>, { pub fn new(n: usize) -> Self { Self { pos: vec![], g: (0..n).map(|_| vec![]).collect(), cost_sum: T::zero(), } } pub fn get_edge(&self, i: usize) -> MinCostFlowEdge<T> { assert!(i < self.pos.len()); let e = &self.g[self.pos[i].0][self.pos[i].1]; let re = &self.g[e.to][e.rev]; MinCostFlowEdge { from: self.pos[i].0, to: e.to, cap: e.cap + re.cap, flow: re.cap, cost: e.cost, } } pub fn edges(&self) -> Vec<MinCostFlowEdge<T>> { let m = self.pos.len(); let mut result = vec![]; for i in 0..m { result.push(self.get_edge(i)); } result } pub fn add_edge(&mut self, from: usize, to: usize, cap: T, cost: T) -> usize { assert!(from < self.g.len()); assert!(to < self.g.len()); assert_ne!(from, to); assert!(cap >= T::zero()); assert!(cost >= T::zero()); self.pos.push((from, self.g[from].len())); self.cost_sum += cost; let rev = self.g[to].len(); self.g[from].push(_Edge { to, rev, cap, cost }); let rev = self.g[from].len() - 1; self.g[to].push(_Edge { to: from, rev, cap: T::zero(), cost: -cost, }); self.pos.len() - 1 } /// Returns (maximum flow, cost) pub fn flow(&mut self, source: usize, sink: usize, flow_limit: T) -> (T, T) { self.slope(source, sink, flow_limit).pop().unwrap() } pub fn slope(&mut self, source: usize, sink: usize, flow_limit: T) -> Vec<(T, T)> { let n = self.g.len(); assert!(source < n); assert!(sink < n); assert_ne!(source, sink); let mut dual = vec![T::zero(); n]; let mut prev_v = vec![0; n]; let mut prev_e = vec![0; n]; let mut flow = T::zero(); let mut cost = T::zero(); let mut prev_cost: Option<T> = None; let mut result = vec![(flow, cost)]; while flow < flow_limit { if !self.refine_dual(source, sink, &mut dual, &mut prev_v, &mut prev_e) { break; } let mut c = flow_limit - flow; let mut v = sink; while v != source { c = std::cmp::min(c, self.g[prev_v[v]][prev_e[v]].cap); v = prev_v[v]; } let mut v = sink; while v != source { self.g[prev_v[v]][prev_e[v]].cap -= c; let rev = self.g[prev_v[v]][prev_e[v]].rev; self.g[v][rev].cap += c; v = prev_v[v]; } let d = -dual[source]; flow += c; cost += d * c; if prev_cost == Some(d) { assert!(result.pop().is_some()); } result.push((flow, cost)); prev_cost = Some(cost); } result } fn refine_dual( &self, source: usize, sink: usize, dual: &mut [T], pv: &mut [usize], pe: &mut [usize], ) -> bool { let n = self.g.len(); let mut dist = vec![self.cost_sum; n]; let mut vis = vec![false; n]; let mut que = std::collections::BinaryHeap::new(); dist[source] = T::zero(); que.push((std::cmp::Reverse(T::zero()), source)); while let Some((_, v)) = que.pop() { if vis[v] { continue; } vis[v] = true; if v == sink { break; } for (i, e) in self.g[v].iter().enumerate() { if vis[e.to] || e.cap == T::zero() { continue; } let cost = e.cost - dual[e.to] + dual[v]; if dist[e.to] - dist[v] > cost { dist[e.to] = dist[v] + cost; pv[e.to] = v; pe[e.to] = i; que.push((std::cmp::Reverse(dist[e.to]), e.to)); } } } if !vis[sink] { return false; } for v in 0..n { if !vis[v] { continue; } dual[v] -= dist[sink] - dist[v]; } true } } struct _Edge<T> { to: usize, rev: usize, cap: T, cost: T, } #[cfg(test)] mod tests { use super::*; #[test] fn test_min_cost_flow() { let mut graph = MinCostFlowGraph::new(4); graph.add_edge(0, 1, 2, 1); graph.add_edge(0, 2, 1, 2); graph.add_edge(1, 2, 1, 1); graph.add_edge(1, 3, 1, 3); graph.add_edge(2, 3, 2, 1); let (flow, cost) = graph.flow(0, 3, 2); assert_eq!(flow, 2); assert_eq!(cost, 6); } } } use mincostflow::*;