QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#756260 | #9558. The Devil | ucup-team296# | TL | 0ms | 2284kb | Rust | 74.9kb | 2024-11-16 19:34:13 | 2024-11-16 19:34:14 |
Judging History
answer
// https://contest.ucup.ac/contest/1843/problem/9558
pub mod solution {
//{"name":"K. The Devil","group":"Universal Cup - The 3rd Universal Cup. Stage 17: Jinan","url":"https://contest.ucup.ac/contest/1843/problem/9558","interactive":false,"timeLimit":1000,"tests":[{"input":"5\nautomated teller machine\nactive teller machine\nactive trouble maker\nalways telling misinformation\nAmerican Teller Machinery\n","output":"atm\natma\nactm\natem\nATM\n"},{"input":"5\nForest Conservation Committee Forum\nFuming Corruption Collusion Federation\nFulsome Cash Concealment Foundation\nFunky Crony Capitalism Facilitator\nFunny Cocky Cocky Funny\n","output":"FCCF\nFCCoF\nFCCFo\nFuCCF\nFCoCF\n"},{"input":"3\nA AA\nAA A\nA A A\n","output":"no solution\n"}],"testType":"single","input":{"type":"stdin","fileName":null,"pattern":null},"output":{"type":"stdout","fileName":null,"pattern":null},"languages":{"java":{"taskClass":"KTheDevil"}}}
use crate::algo_lib::collections::default_map::default_hash_map::DefaultHashMap;
use crate::algo_lib::collections::fx_hash_map::FxHashSet;
use crate::algo_lib::collections::iter_ext::collect::IterCollect;
use crate::algo_lib::collections::slice_ext::indices::Indices;
use crate::algo_lib::graph::edges::edge_trait::EdgeTrait;
use crate::algo_lib::graph::edges::flow_edge_trait::FlowEdgeTrait;
use crate::algo_lib::graph::edges::weighted_flow_edge::WeightedFlowEdge;
use crate::algo_lib::graph::min_cost_flow::CostAndFlow;
use crate::algo_lib::graph::min_cost_flow::MinCostFlow;
use crate::algo_lib::graph::Graph;
use crate::algo_lib::io::input::Input;
use crate::algo_lib::io::output::Output;
use crate::algo_lib::misc::test_type::TaskType;
use crate::algo_lib::misc::test_type::TestType;
use crate::algo_lib::string::str::Str;
use crate::algo_lib::string::str::StrReader;
type PreCalc = ();
fn solve(input: &mut Input, out: &mut Output, _test_case: usize, _data: &mut PreCalc) {
let n = input.read_size();
let s = (0..n)
.map(|_| {
input
.read_line()
.split(' ')
.into_iter()
.map(|x| x.into_owned())
.collect_vec()
})
.collect_vec();
let mut map = DefaultHashMap::<_, Vec<_>>::new();
let mut done = FxHashSet::default();
for i in 0..n {
let key = Str::from(s[i].iter().map(|x| x[0]).collect_vec());
map[key].push((i, vec![1; s[i].len()]));
done.insert((i, vec![1; s[i].len()]));
}
loop {
let mut graph = Graph::new(map.len() + n + 2);
let source = graph.vertex_count() - 2;
let sink = graph.vertex_count() - 1;
for (i, (w, val)) in map.iter().enumerate() {
graph.add_edge(WeightedFlowEdge::new(source, i, w.len() as i64, 1));
for &(j, _) in val {
graph.add_edge(WeightedFlowEdge::new(i, map.len() + j, 0, 1));
}
}
for i in 0..n {
graph.add_edge(WeightedFlowEdge::new(map.len() + i, sink, 0, 1));
}
let CostAndFlow { flow, .. } = graph.min_cost_max_flow(source, sink);
if flow == n as i64 {
let mut ans = vec![Str::new(); n];
for (i, (w, _)) in map.iter().enumerate() {
for edge in &graph[i] {
let to = edge.to();
if to >= map.len() && to < map.len() + n && edge.flow(&graph) == 1 {
ans[to - map.len()] = w.clone();
}
}
}
out.print_per_line(&ans);
return;
}
let mut to_add = Vec::new();
for (i, (_, val)) in map.iter().enumerate() {
if graph[source][i].flow(&graph) == 0 {
continue;
}
for (id, v) in val {
let id = *id;
for j in v.indices() {
if v[j] == s[id][j].len() {
continue;
}
let mut nv = v.clone();
nv[j] += 1;
if done.contains(&(id, nv.clone())) {
continue;
}
done.insert((id, nv.clone()));
let word = Str::from(
nv.iter()
.enumerate()
.flat_map(|(pos, &x)| s[id][pos].iter().take(x))
.collect_vec(),
);
to_add.push((word, (id, nv)));
}
}
}
if to_add.is_empty() {
out.print_line("no solution");
return;
}
for (word, (id, v)) in to_add {
map[word].push((id, v));
}
}
}
pub static TEST_TYPE: TestType = TestType::Single;
pub static TASK_TYPE: TaskType = TaskType::Classic;
pub(crate) fn run(mut input: Input, mut output: Output) -> bool {
let mut pre_calc = ();
match TEST_TYPE {
TestType::Single => solve(&mut input, &mut output, 1, &mut pre_calc),
TestType::MultiNumber => {
let t = input.read();
for i in 1..=t {
solve(&mut input, &mut output, i, &mut pre_calc);
}
}
TestType::MultiEof => {
let mut i = 1;
while input.peek().is_some() {
solve(&mut input, &mut output, i, &mut pre_calc);
i += 1;
}
}
}
output.flush();
match TASK_TYPE {
TaskType::Classic => input.is_empty(),
TaskType::Interactive => true,
}
}
}
pub mod algo_lib {
#![allow(clippy::too_many_arguments)]
#![allow(clippy::type_complexity)]
#![allow(clippy::missing_safety_doc)]
#![allow(clippy::legacy_numeric_constants)]
pub mod collections {
pub mod default_map {
pub mod default_hash_map {
use crate::algo_lib::collections::fx_hash_map::FxHashMap;
use std::hash::Hash;
use std::iter::FromIterator;
use std::ops::Deref;
use std::ops::DerefMut;
use std::ops::Index;
use std::ops::IndexMut;
#[derive(Default, Clone, Eq, PartialEq, Debug)]
pub struct DefaultHashMap<K: Hash + Eq, V>(FxHashMap<K, V>, V);
impl<K: Hash + Eq, V> Deref for DefaultHashMap<K, V> {
type Target = FxHashMap<K, V>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<K: Hash + Eq, V> DerefMut for DefaultHashMap<K, V> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<K: Hash + Eq, V: Default> DefaultHashMap<K, V> {
pub fn new() -> Self {
Self(FxHashMap::default(), V::default())
}
pub fn get(&self, key: &K) -> &V {
self.0.get(key).unwrap_or(&self.1)
}
pub fn get_mut(&mut self, key: K) -> &mut V {
self.0.entry(key).or_insert_with(|| V::default())
}
pub fn into_values(self) -> std::collections::hash_map::IntoValues<K, V> {
self.0.into_values()
}
}
impl<K: Hash + Eq, V: Default> Index<K> for DefaultHashMap<K, V> {
type Output = V;
fn index(&self, index: K) -> &Self::Output {
self.get(&index)
}
}
impl<K: Hash + Eq, V: Default> IndexMut<K> for DefaultHashMap<K, V> {
fn index_mut(&mut self, index: K) -> &mut Self::Output {
self.get_mut(index)
}
}
impl<K: Hash + Eq, V> IntoIterator for DefaultHashMap<K, V> {
type Item = (K, V);
type IntoIter = std::collections::hash_map::IntoIter<K, V>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<K: Hash + Eq, V: Default> FromIterator<(K, V)> for DefaultHashMap<K, V> {
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
Self(iter.into_iter().collect(), V::default())
}
}
}
}
pub mod dsu {
use crate::algo_lib::collections::iter_ext::collect::IterCollect;
use crate::algo_lib::collections::slice_ext::bounds::Bounds;
use crate::algo_lib::collections::slice_ext::legacy_fill::LegacyFill;
use std::cell::Cell;
#[derive(Clone)]
pub struct DSU {
id: Vec<Cell<u32>>,
size: Vec<u32>,
count: usize,
}
impl DSU {
pub fn new(n: usize) -> Self {
Self {
id: (0..n).map(|i| Cell::new(i as u32)).collect_vec(),
size: vec![1; n],
count: n,
}
}
pub fn size(&self, i: usize) -> usize {
self.size[self.get(i)] as usize
}
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize {
self.id.len()
}
pub fn iter(&self) -> impl Iterator<Item = usize> + '_ {
self.id.iter().enumerate().filter_map(|(i, id)| {
if (i as u32) == id.get() {
Some(i)
} else {
None
}
})
}
pub fn set_count(&self) -> usize {
self.count
}
pub fn join(&mut self, mut a: usize, mut b: usize) -> bool {
a = self.get(a);
b = self.get(b);
if a == b {
false
} else {
self.size[a] += self.size[b];
self.id[b].replace(a as u32);
self.count -= 1;
true
}
}
pub fn get(&self, i: usize) -> usize {
if self.id[i].get() != i as u32 {
let res = self.get(self.id[i].get() as usize);
self.id[i].replace(res as u32);
}
self.id[i].get() as usize
}
pub fn clear(&mut self) {
self.count = self.id.len();
self.size.legacy_fill(1);
self.id.iter().enumerate().for_each(|(i, id)| {
id.replace(i as u32);
});
}
pub fn parts(&self) -> Vec<Vec<usize>> {
let roots = self.iter().collect_vec();
let mut res = vec![Vec::new(); roots.len()];
for i in 0..self.id.len() {
res[roots.as_slice().bin_search(&self.get(i)).unwrap()].push(i);
}
res
}
}
}
pub mod fx_hash_map {
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::cell::Cell;
use std::convert::TryInto;
use std::time::SystemTime;
use std::collections::HashMap;
use std::collections::HashSet;
use std::hash::BuildHasherDefault;
use std::hash::Hasher;
use std::mem::size_of;
use std::ops::BitXor;
pub type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
pub type FxHashSet<V> = HashSet<V, BuildHasherDefault<FxHasher>>;
#[derive(Default)]
pub struct FxHasher {
hash: usize,
}
thread_local! {
static K: Cell<usize> = Cell::new(
((SystemTime::UNIX_EPOCH.elapsed().unwrap().as_nanos().wrapping_mul(2) + 1) & 0xFFFFFFFFFFFFFFFF) as usize
);
}
impl FxHasher {
#[inline]
fn add_to_hash(&mut self, i: usize) {
self.hash = self
.hash
.rotate_left(5)
.bitxor(i)
.wrapping_mul(K.with(|k| k.get()));
}
}
impl Hasher for FxHasher {
#[inline]
fn write(&mut self, mut bytes: &[u8]) {
let read_usize = |bytes: &[u8]| u64::from_ne_bytes(bytes[..8].try_into().unwrap());
let mut hash = FxHasher { hash: self.hash };
while bytes.len() >= size_of::<usize>() {
hash.add_to_hash(read_usize(bytes) as usize);
bytes = &bytes[size_of::<usize>()..];
}
if (size_of::<usize>() > 4) && (bytes.len() >= 4) {
hash.add_to_hash(u32::from_ne_bytes(bytes[..4].try_into().unwrap()) as usize);
bytes = &bytes[4..];
}
if (size_of::<usize>() > 2) && bytes.len() >= 2 {
hash.add_to_hash(u16::from_ne_bytes(bytes[..2].try_into().unwrap()) as usize);
bytes = &bytes[2..];
}
if (size_of::<usize>() > 1) && !bytes.is_empty() {
hash.add_to_hash(bytes[0] as usize);
}
self.hash = hash.hash;
}
#[inline]
fn write_u8(&mut self, i: u8) {
self.add_to_hash(i as usize);
}
#[inline]
fn write_u16(&mut self, i: u16) {
self.add_to_hash(i as usize);
}
#[inline]
fn write_u32(&mut self, i: u32) {
self.add_to_hash(i as usize);
}
#[inline]
fn write_u64(&mut self, i: u64) {
self.add_to_hash(i as usize);
}
#[inline]
fn write_usize(&mut self, i: usize) {
self.add_to_hash(i);
}
#[inline]
fn finish(&self) -> u64 {
self.hash as u64
}
}
}
pub mod indexed_heap {
use crate::algo_lib::collections::slice_ext::legacy_fill::LegacyFill;
use std::mem;
#[derive(Default)]
enum Opt<T> {
#[default]
None,
Some(u32, T),
}
impl<T> Opt<T> {
fn index(&self) -> usize {
match self {
Opt::None => panic!("unreachable"),
Opt::Some(index, _) => *index as usize,
}
}
fn val(&self) -> &T {
match self {
Opt::None => panic!("unreachable"),
Opt::Some(_, val) => val,
}
}
fn set_index(&mut self, index: usize) {
match self {
Opt::None => panic!("unreachable"),
Opt::Some(ind, _) => {
*ind = index as u32;
}
}
}
fn set_val(&mut self, t: T) {
match self {
Opt::None => panic!("unreachable"),
Opt::Some(_, val) => {
*val = t;
}
}
}
fn take(&mut self) -> (usize, T) {
let val = mem::take(self);
match val {
Opt::None => panic!("unreachable"),
Opt::Some(ind, val) => (ind as usize, val),
}
}
}
impl<T> Clone for Opt<T> {
fn clone(&self) -> Self {
match self {
Opt::None => Opt::None,
Opt::Some(..) => panic!("unreachable"),
}
}
}
pub struct IndexedHeap<T> {
heap: Vec<u32>,
pos: Vec<Opt<T>>,
}
impl<T: PartialOrd> IndexedHeap<T> {
pub fn new(capacity: usize) -> Self {
Self {
heap: Vec::with_capacity(capacity),
pos: vec![Opt::None; capacity],
}
}
pub fn len(&self) -> usize {
self.heap.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn iter(&self) -> impl Iterator<Item = usize> + '_ {
self.heap.iter().map(|x| *x as usize)
}
pub fn add_or_adjust(&mut self, el: usize, val: T) {
match self.pos[el] {
Opt::None => {
self.pos[el] = Opt::Some(self.heap.len() as u32, val);
self.heap.push(el as u32);
}
Opt::Some(..) => {
self.pos[el].set_val(val);
}
}
self.sift_up(self.pos[el].index());
self.sift_down(self.pos[el].index());
}
pub fn add_or_relax(&mut self, el: usize, val: T) {
match &self.pos[el] {
Opt::None => {
self.add_or_adjust(el, val);
}
Opt::Some(_, value) => {
if &val < value {
self.add_or_adjust(el, val);
}
}
}
}
pub fn peek(&self) -> Option<(usize, &T)> {
if self.is_empty() {
None
} else {
let at = self.heap[0] as usize;
Some((self.pos[at].index(), self.pos[at].val()))
}
}
pub fn pop(&mut self) -> Option<(usize, T)> {
if self.is_empty() {
None
} else {
let el = self.heap[0] as usize;
Some((el, self.remove(el).unwrap()))
}
}
pub fn clear(&mut self) {
self.heap.clear();
self.pos.legacy_fill(Opt::None);
}
pub fn remove(&mut self, el: usize) -> Option<T> {
match self.pos[el] {
Opt::None => None,
Opt::Some(pos, _) => {
let last = self.heap.pop().unwrap();
let val = self.pos[last as usize].take().1;
if self.is_empty() {
Some(val)
} else {
let top_val = self.pos[el].take().1;
self.pos[last as usize] = Opt::Some(pos, val);
self.heap[pos as usize] = last;
self.sift_down(pos as usize);
self.sift_up(pos as usize);
Some(top_val)
}
}
}
}
pub fn value(&self, el: usize) -> Option<&T> {
match &self.pos[el] {
Opt::None => None,
Opt::Some(_, val) => Some(val),
}
}
fn sift_up(&mut self, mut index: usize) {
let v = self.heap[index] as usize;
while index > 0 {
let parent = (index - 1) >> 1;
let par_val = self.heap[parent] as usize;
if self.pos[par_val].val() <= self.pos[v].val() {
self.heap[index] = v as u32;
self.pos[v].set_index(index);
return;
}
self.heap[index] = par_val as u32;
self.pos[par_val].set_index(index);
index = parent;
}
self.heap[0] = v as u32;
self.pos[v].set_index(0);
}
fn sift_down(&mut self, mut index: usize) {
let v = self.heap[index] as usize;
loop {
let mut child = (index << 1) + 1;
if child >= self.len() {
break;
}
if child + 1 < self.len()
&& self.pos[self.heap[child] as usize].val()
> self.pos[self.heap[child + 1] as usize].val()
{
child += 1;
}
if self.pos[self.heap[child] as usize].val() >= self.pos[v].val() {
break;
}
self.heap[index] = self.heap[child];
self.pos[self.heap[index] as usize].set_index(index);
index = child;
}
self.heap[index] = v as u32;
self.pos[v].set_index(index);
}
}
}
pub mod iter_ext {
pub mod collect {
pub trait IterCollect<T>: Iterator<Item = T> + Sized {
fn collect_vec(self) -> Vec<T> {
self.collect()
}
}
impl<T, I: Iterator<Item = T> + Sized> IterCollect<T> for I {}
}
}
pub mod min_max {
pub trait MinimMaxim<Rhs = Self>: PartialOrd + Sized {
fn minim(&mut self, other: Rhs) -> bool;
fn maxim(&mut self, other: Rhs) -> bool;
}
impl<T: PartialOrd> MinimMaxim for T {
fn minim(&mut self, other: Self) -> bool {
if other < *self {
*self = other;
true
} else {
false
}
}
fn maxim(&mut self, other: Self) -> bool {
if other > *self {
*self = other;
true
} else {
false
}
}
}
impl<T: PartialOrd> MinimMaxim<T> for Option<T> {
fn minim(&mut self, other: T) -> bool {
match self {
None => {
*self = Some(other);
true
}
Some(v) => v.minim(other),
}
}
fn maxim(&mut self, other: T) -> bool {
match self {
None => {
*self = Some(other);
true
}
Some(v) => v.maxim(other),
}
}
}
}
pub mod slice_ext {
pub mod backward {
use std::ops::Index;
use std::ops::IndexMut;
pub struct Back(pub usize);
impl<T> Index<Back> for [T] {
type Output = T;
fn index(&self, index: Back) -> &Self::Output {
&self[self.len() - index.0 - 1]
}
}
impl<T> IndexMut<Back> for [T] {
fn index_mut(&mut self, index: Back) -> &mut Self::Output {
&mut self[self.len() - index.0 - 1]
}
}
impl<T> Index<Back> for Vec<T> {
type Output = T;
fn index(&self, index: Back) -> &Self::Output {
self.as_slice().index(index)
}
}
impl<T> IndexMut<Back> for Vec<T> {
fn index_mut(&mut self, index: Back) -> &mut Self::Output {
self.as_mut_slice().index_mut(index)
}
}
}
pub mod bounds {
pub trait Bounds<T: PartialOrd> {
fn lower_bound(&self, el: &T) -> usize;
fn upper_bound(&self, el: &T) -> usize;
fn bin_search(&self, el: &T) -> Option<usize>;
fn more(&self, el: &T) -> usize;
fn more_or_eq(&self, el: &T) -> usize;
fn less(&self, el: &T) -> usize;
fn less_or_eq(&self, el: &T) -> usize;
}
impl<T: PartialOrd> Bounds<T> for [T] {
fn lower_bound(&self, el: &T) -> usize {
let mut left = 0;
let mut right = self.len();
while left < right {
let mid = left + ((right - left) >> 1);
if &self[mid] < el {
left = mid + 1;
} else {
right = mid;
}
}
left
}
fn upper_bound(&self, el: &T) -> usize {
let mut left = 0;
let mut right = self.len();
while left < right {
let mid = left + ((right - left) >> 1);
if &self[mid] <= el {
left = mid + 1;
} else {
right = mid;
}
}
left
}
fn bin_search(&self, el: &T) -> Option<usize> {
let at = self.lower_bound(el);
if at == self.len() || &self[at] != el {
None
} else {
Some(at)
}
}
fn more(&self, el: &T) -> usize {
self.len() - self.upper_bound(el)
}
fn more_or_eq(&self, el: &T) -> usize {
self.len() - self.lower_bound(el)
}
fn less(&self, el: &T) -> usize {
self.lower_bound(el)
}
fn less_or_eq(&self, el: &T) -> usize {
self.upper_bound(el)
}
}
}
pub mod indices {
use std::ops::Range;
pub trait Indices {
fn indices(&self) -> Range<usize>;
}
impl<T> Indices for [T] {
fn indices(&self) -> Range<usize> {
0..self.len()
}
}
}
pub mod legacy_fill {
// 1.50
pub trait LegacyFill<T> {
fn legacy_fill(&mut self, val: T);
}
impl<T: Clone> LegacyFill<T> for [T] {
fn legacy_fill(&mut self, val: T) {
for el in self.iter_mut() {
*el = val.clone();
}
}
}
}
}
pub mod vec_ext {
pub mod default {
pub fn default_vec<T: Default>(len: usize) -> Vec<T> {
let mut v = Vec::with_capacity(len);
for _ in 0..len {
v.push(T::default());
}
v
}
}
}
}
pub mod graph {
use crate::algo_lib::collections::dsu::DSU;
use crate::algo_lib::graph::edges::bi_edge::BiEdge;
use crate::algo_lib::graph::edges::edge::Edge;
use crate::algo_lib::graph::edges::edge_trait::BidirectionalEdgeTrait;
use crate::algo_lib::graph::edges::edge_trait::EdgeTrait;
use std::ops::Index;
use std::ops::IndexMut;
#[derive(Clone)]
pub struct Graph<E: EdgeTrait> {
edges: Vec<Vec<E>>,
edge_count: usize,
}
impl<E: EdgeTrait> Graph<E> {
pub fn new(vertex_count: usize) -> Self {
Self {
edges: vec![Vec::new(); vertex_count],
edge_count: 0,
}
}
pub fn add_edge(&mut self, (from, mut edge): (usize, E)) -> usize {
let to = edge.to();
assert!(to < self.vertex_count());
let direct_id = self.edges[from].len();
edge.set_id(self.edge_count);
self.edges[from].push(edge);
if E::REVERSABLE {
let rev_id = self.edges[to].len();
self.edges[from][direct_id].set_reverse_id(rev_id);
let mut rev_edge = self.edges[from][direct_id].reverse_edge(from);
rev_edge.set_id(self.edge_count);
rev_edge.set_reverse_id(direct_id);
self.edges[to].push(rev_edge);
}
self.edge_count += 1;
direct_id
}
pub fn add_vertices(&mut self, cnt: usize) {
self.edges.resize(self.edges.len() + cnt, Vec::new());
}
pub fn clear(&mut self) {
self.edge_count = 0;
for ve in self.edges.iter_mut() {
ve.clear();
}
}
pub fn vertex_count(&self) -> usize {
self.edges.len()
}
pub fn edge_count(&self) -> usize {
self.edge_count
}
pub fn degrees(&self) -> Vec<usize> {
self.edges.iter().map(|v| v.len()).collect()
}
}
impl<E: BidirectionalEdgeTrait> Graph<E> {
pub fn is_tree(&self) -> bool {
if self.edge_count + 1 != self.vertex_count() {
false
} else {
self.is_connected()
}
}
pub fn is_forest(&self) -> bool {
let mut dsu = DSU::new(self.vertex_count());
for i in 0..self.vertex_count() {
for e in self[i].iter() {
if i <= e.to() && !dsu.join(i, e.to()) {
return false;
}
}
}
true
}
pub fn is_connected(&self) -> bool {
let mut dsu = DSU::new(self.vertex_count());
for i in 0..self.vertex_count() {
for e in self[i].iter() {
dsu.join(i, e.to());
}
}
dsu.set_count() == 1
}
}
impl<E: EdgeTrait> Index<usize> for Graph<E> {
type Output = [E];
fn index(&self, index: usize) -> &Self::Output {
&self.edges[index]
}
}
impl<E: EdgeTrait> IndexMut<usize> for Graph<E> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.edges[index]
}
}
impl Graph<Edge<()>> {
pub fn from_edges(n: usize, edges: &[(usize, usize)]) -> Self {
let mut graph = Self::new(n);
for &(from, to) in edges {
graph.add_edge(Edge::new(from, to));
}
graph
}
}
impl<P: Clone> Graph<Edge<P>> {
pub fn from_edges_with_payload(n: usize, edges: &[(usize, usize, P)]) -> Self {
let mut graph = Self::new(n);
for (from, to, p) in edges.iter() {
graph.add_edge(Edge::with_payload(*from, *to, p.clone()));
}
graph
}
}
impl Graph<BiEdge<()>> {
pub fn from_biedges(n: usize, edges: &[(usize, usize)]) -> Self {
let mut graph = Self::new(n);
for &(from, to) in edges {
graph.add_edge(BiEdge::new(from, to));
}
graph
}
}
impl<P: Clone> Graph<BiEdge<P>> {
pub fn from_biedges_with_payload(n: usize, edges: &[(usize, usize, P)]) -> Self {
let mut graph = Self::new(n);
for (from, to, p) in edges.iter() {
graph.add_edge(BiEdge::with_payload(*from, *to, p.clone()));
}
graph
}
}
pub mod edges {
pub mod bi_edge {
use crate::algo_lib::graph::edges::bi_edge_trait::BiEdgeTrait;
use crate::algo_lib::graph::edges::edge_id::EdgeId;
use crate::algo_lib::graph::edges::edge_id::NoId;
use crate::algo_lib::graph::edges::edge_id::WithId;
use crate::algo_lib::graph::edges::edge_trait::BidirectionalEdgeTrait;
use crate::algo_lib::graph::edges::edge_trait::EdgeTrait;
#[derive(Clone)]
pub struct BiEdgeRaw<Id: EdgeId, P> {
to: u32,
id: Id,
payload: P,
}
impl<Id: EdgeId> BiEdgeRaw<Id, ()> {
pub fn new(from: usize, to: usize) -> (usize, Self) {
(
from,
Self {
to: to as u32,
id: Id::new(),
payload: (),
},
)
}
}
impl<Id: EdgeId, P> BiEdgeRaw<Id, P> {
pub fn with_payload(from: usize, to: usize, payload: P) -> (usize, Self) {
(from, Self::with_payload_impl(to, payload))
}
fn with_payload_impl(to: usize, payload: P) -> BiEdgeRaw<Id, P> {
Self {
to: to as u32,
id: Id::new(),
payload,
}
}
}
impl<Id: EdgeId, P: Clone> BidirectionalEdgeTrait for BiEdgeRaw<Id, P> {}
impl<Id: EdgeId, P: Clone> EdgeTrait for BiEdgeRaw<Id, P> {
type Payload = P;
const REVERSABLE: bool = true;
fn to(&self) -> usize {
self.to as usize
}
fn id(&self) -> usize {
self.id.id()
}
fn set_id(&mut self, id: usize) {
self.id.set_id(id);
}
fn reverse_id(&self) -> usize {
panic!("no reverse id")
}
fn set_reverse_id(&mut self, _: usize) {}
fn reverse_edge(&self, from: usize) -> Self {
Self::with_payload_impl(from, self.payload.clone())
}
fn payload(&self) -> &P {
&self.payload
}
}
impl<Id: EdgeId, P: Clone> BiEdgeTrait for BiEdgeRaw<Id, P> {}
pub type BiEdge<P> = BiEdgeRaw<NoId, P>;
pub type BiEdgeWithId<P> = BiEdgeRaw<WithId, P>;
}
pub mod bi_edge_trait {
use crate::algo_lib::graph::edges::edge_trait::EdgeTrait;
pub trait BiEdgeTrait: EdgeTrait {}
}
pub mod edge {
use crate::algo_lib::graph::edges::edge_id::EdgeId;
use crate::algo_lib::graph::edges::edge_id::NoId;
use crate::algo_lib::graph::edges::edge_id::WithId;
use crate::algo_lib::graph::edges::edge_trait::EdgeTrait;
#[derive(Clone)]
pub struct EdgeRaw<Id: EdgeId, P> {
to: u32,
id: Id,
payload: P,
}
impl<Id: EdgeId> EdgeRaw<Id, ()> {
pub fn new(from: usize, to: usize) -> (usize, Self) {
(
from,
Self {
to: to as u32,
id: Id::new(),
payload: (),
},
)
}
}
impl<Id: EdgeId, P> EdgeRaw<Id, P> {
pub fn with_payload(from: usize, to: usize, payload: P) -> (usize, Self) {
(from, Self::with_payload_impl(to, payload))
}
fn with_payload_impl(to: usize, payload: P) -> Self {
Self {
to: to as u32,
id: Id::new(),
payload,
}
}
}
impl<Id: EdgeId, P: Clone> EdgeTrait for EdgeRaw<Id, P> {
type Payload = P;
const REVERSABLE: bool = false;
fn to(&self) -> usize {
self.to as usize
}
fn id(&self) -> usize {
self.id.id()
}
fn set_id(&mut self, id: usize) {
self.id.set_id(id);
}
fn reverse_id(&self) -> usize {
panic!("no reverse")
}
fn set_reverse_id(&mut self, _: usize) {
panic!("no reverse")
}
fn reverse_edge(&self, _: usize) -> Self {
panic!("no reverse")
}
fn payload(&self) -> &P {
&self.payload
}
}
pub type Edge<P> = EdgeRaw<NoId, P>;
pub type EdgeWithId<P> = EdgeRaw<WithId, P>;
}
pub mod edge_id {
pub trait EdgeId: Clone {
fn new() -> Self;
fn id(&self) -> usize;
fn set_id(&mut self, id: usize);
}
#[derive(Clone)]
pub struct WithId {
id: u32,
}
impl EdgeId for WithId {
fn new() -> Self {
Self { id: 0 }
}
fn id(&self) -> usize {
self.id as usize
}
fn set_id(&mut self, id: usize) {
self.id = id as u32;
}
}
#[derive(Clone)]
pub struct NoId {}
impl EdgeId for NoId {
fn new() -> Self {
Self {}
}
fn id(&self) -> usize {
panic!("Id called on no id")
}
fn set_id(&mut self, _: usize) {}
}
}
pub mod edge_trait {
pub trait EdgeTrait: Clone {
type Payload;
const REVERSABLE: bool;
fn to(&self) -> usize;
fn id(&self) -> usize;
fn set_id(&mut self, id: usize);
fn reverse_id(&self) -> usize;
fn set_reverse_id(&mut self, reverse_id: usize);
#[must_use]
fn reverse_edge(&self, from: usize) -> Self;
fn payload(&self) -> &Self::Payload;
}
pub trait BidirectionalEdgeTrait: EdgeTrait {}
}
pub mod flow_edge_trait {
use crate::algo_lib::graph::edges::edge_trait::EdgeTrait;
use crate::algo_lib::graph::Graph;
use crate::algo_lib::numbers::num_traits::algebra::AdditionMonoidWithSub;
pub trait FlowEdgeTrait<C: AdditionMonoidWithSub + PartialOrd + Copy>: EdgeTrait {
fn capacity(&self) -> C;
fn capacity_mut(&mut self) -> &mut C;
fn flow(&self, graph: &Graph<Self>) -> C;
fn push_flow(&self, flow: C) -> (usize, usize, C) {
(self.to(), self.reverse_id(), flow)
}
}
}
pub mod weighted_edge_trait {
use crate::algo_lib::graph::edges::edge_trait::EdgeTrait;
pub trait WeightedEdgeTrait<W: Copy>: EdgeTrait {
fn weight(&self) -> W;
fn weight_mut(&mut self) -> &mut W;
}
}
pub mod weighted_flow_edge {
use crate::algo_lib::graph::edges::edge_id::EdgeId;
use crate::algo_lib::graph::edges::edge_id::NoId;
use crate::algo_lib::graph::edges::edge_id::WithId;
use crate::algo_lib::graph::edges::edge_trait::EdgeTrait;
use crate::algo_lib::graph::edges::flow_edge_trait::FlowEdgeTrait;
use crate::algo_lib::graph::edges::weighted_edge_trait::WeightedEdgeTrait;
use crate::algo_lib::graph::Graph;
use crate::algo_lib::numbers::num_traits::algebra::AdditionGroup;
use crate::algo_lib::numbers::num_traits::algebra::AdditionMonoidWithSub;
#[derive(Clone)]
pub struct WeightedFlowEdgeRaw<
W: AdditionGroup + Copy,
C: AdditionMonoidWithSub + Ord + Copy,
Id: EdgeId,
P,
> {
to: u32,
weight: W,
capacity: C,
reverse_id: u32,
id: Id,
payload: P,
}
impl<W: AdditionGroup + Copy, C: AdditionMonoidWithSub + Ord + Copy, Id: EdgeId>
WeightedFlowEdgeRaw<W, C, Id, ()>
{
pub fn new(from: usize, to: usize, w: W, c: C) -> (usize, Self) {
(
from,
Self {
to: to as u32,
weight: w,
capacity: c,
reverse_id: 0,
id: Id::new(),
payload: (),
},
)
}
}
impl<W: AdditionGroup + Copy, C: AdditionMonoidWithSub + Ord + Copy, Id: EdgeId, P>
WeightedFlowEdgeRaw<W, C, Id, P>
{
pub fn with_payload(from: usize, to: usize, w: W, c: C, payload: P) -> (usize, Self) {
(from, Self::with_payload_impl(to, w, c, payload))
}
fn with_payload_impl(to: usize, w: W, c: C, payload: P) -> Self {
Self {
to: to as u32,
weight: w,
capacity: c,
reverse_id: 0,
id: Id::new(),
payload,
}
}
}
impl<
W: AdditionGroup + Copy,
C: AdditionMonoidWithSub + Ord + Copy,
Id: EdgeId,
P: Clone + Default,
> EdgeTrait for WeightedFlowEdgeRaw<W, C, Id, P>
{
type Payload = P;
const REVERSABLE: bool = true;
fn to(&self) -> usize {
self.to as usize
}
fn id(&self) -> usize {
self.id.id()
}
fn set_id(&mut self, id: usize) {
self.id.set_id(id);
}
fn reverse_id(&self) -> usize {
self.reverse_id as usize
}
fn set_reverse_id(&mut self, reverse_id: usize) {
self.reverse_id = reverse_id as u32;
}
fn reverse_edge(&self, from: usize) -> Self {
Self::with_payload_impl(from, -self.weight, C::zero(), P::default())
}
fn payload(&self) -> &P {
&self.payload
}
}
impl<
W: AdditionGroup + Copy,
C: AdditionMonoidWithSub + Ord + Copy,
Id: EdgeId,
P: Clone + Default,
> WeightedEdgeTrait<W> for WeightedFlowEdgeRaw<W, C, Id, P>
{
fn weight(&self) -> W {
self.weight
}
fn weight_mut(&mut self) -> &mut W {
&mut self.weight
}
}
impl<
W: AdditionGroup + Copy,
C: AdditionMonoidWithSub + Ord + Copy,
Id: EdgeId,
P: Clone + Default,
> FlowEdgeTrait<C> for WeightedFlowEdgeRaw<W, C, Id, P>
{
fn capacity(&self) -> C {
self.capacity
}
fn capacity_mut(&mut self) -> &mut C {
&mut self.capacity
}
fn flow(&self, graph: &Graph<Self>) -> C {
graph[self.to as usize][self.reverse_id as usize].capacity
}
}
pub type WeightedFlowEdge<W, C, P> = WeightedFlowEdgeRaw<W, C, NoId, P>;
pub type WeightedFlowEdgeWithId<W, C, P> = WeightedFlowEdgeRaw<W, C, WithId, P>;
}
}
pub mod flow_graph {
use crate::algo_lib::graph::edges::flow_edge_trait::FlowEdgeTrait;
use crate::algo_lib::graph::Graph;
use crate::algo_lib::numbers::num_traits::algebra::AdditionMonoidWithSub;
pub trait FlowGraph<C: AdditionMonoidWithSub + PartialOrd + Copy, E: FlowEdgeTrait<C>> {
fn push_flow(&mut self, push_data: (usize, usize, C));
}
impl<C: AdditionMonoidWithSub + PartialOrd + Copy, E: FlowEdgeTrait<C>> FlowGraph<C, E>
for Graph<E>
{
fn push_flow(&mut self, (to, reverse_id, flow): (usize, usize, C)) {
*self.edges[to][reverse_id].capacity_mut() += flow;
let from = self.edges[to][reverse_id].to();
let direct_id = self.edges[to][reverse_id].reverse_id();
let direct = &mut self.edges[from][direct_id];
assert!(flow >= C::zero() && flow <= direct.capacity());
*direct.capacity_mut() -= flow;
}
}
}
pub mod min_cost_flow {
use crate::algo_lib::collections::indexed_heap::IndexedHeap;
use crate::algo_lib::collections::min_max::MinimMaxim;
use crate::algo_lib::collections::slice_ext::legacy_fill::LegacyFill;
use crate::algo_lib::graph::edges::edge_id::EdgeId;
use crate::algo_lib::graph::edges::edge_trait::EdgeTrait;
use crate::algo_lib::graph::edges::flow_edge_trait::FlowEdgeTrait;
use crate::algo_lib::graph::edges::weighted_edge_trait::WeightedEdgeTrait;
use crate::algo_lib::graph::edges::weighted_flow_edge::WeightedFlowEdgeRaw;
use crate::algo_lib::graph::flow_graph::FlowGraph;
use crate::algo_lib::graph::Graph;
use crate::algo_lib::numbers::num_traits::algebra::Ring;
use crate::algo_lib::numbers::num_traits::bit_ops::Bits;
use crate::algo_lib::numbers::num_traits::ord::MinMax;
use std::fmt::Display;
pub struct CostAndFlow<C> {
pub cost: C,
pub flow: C,
}
pub trait MinCostFlow<C> {
fn min_cost_flow(&mut self, source: usize, sink: usize) -> CostAndFlow<C>;
fn min_cost_max_flow(&mut self, source: usize, sink: usize) -> CostAndFlow<C>;
}
fn min_cost_flow_impl<C, Id, P: Clone + Default>(
or_graph: &mut Graph<WeightedFlowEdgeRaw<C, C, Id, P>>,
source: usize,
sink: usize,
take_positive_cycles: bool,
) -> CostAndFlow<C>
where
C: Ring + Ord + Copy + MinMax + Bits + Display,
Id: EdgeId,
{
let inf = C::max_val() >> 1;
let n = or_graph.vertex_count();
let mut p = vec![C::zero(); n + 1];
p[n] = inf;
let mut graph = Graph::new(n + 1);
let mut corresponding = Vec::new();
let mut max_capacity = C::zero();
let mut sum_weight = C::zero();
for i in 0..n {
for (j, e) in or_graph[i].iter().enumerate() {
if e.capacity() > C::zero() {
max_capacity.maxim(e.capacity());
sum_weight += e.weight().max(C::zero() - e.weight());
corresponding.push((
i,
j,
graph.add_edge(WeightedFlowEdgeRaw::new(i, e.to(), e.weight(), C::zero())),
));
}
}
}
let mut bits = 0usize;
while (C::one() << bits) <= max_capacity {
bits += 1;
}
let back = graph.add_edge(WeightedFlowEdgeRaw::new(
sink,
source,
if take_positive_cycles {
C::zero() - sum_weight - C::one()
} else {
C::zero()
},
C::zero(),
));
for i in 0..n {
graph.add_edge(WeightedFlowEdgeRaw::new(n, i, C::zero(), C::one()));
}
let mut dis = vec![C::zero(); n + 1];
let mut pre = vec![(0usize, 0usize); n + 1];
let mut heap = IndexedHeap::new(n + 1);
let c = |from: usize, e: &WeightedFlowEdgeRaw<C, C, Id, ()>, p: &Vec<C>| -> C {
p[from] + e.weight() - p[e.to()]
};
let dijkstra = |graph: &mut Graph<WeightedFlowEdgeRaw<C, C, Id, ()>>,
dis: &mut Vec<C>,
pre: &mut Vec<(usize, usize)>,
heap: &mut IndexedHeap<C>,
p: &Vec<C>,
s: usize| {
dis.legacy_fill(inf);
dis[s] = C::zero();
assert!(heap.is_empty());
heap.add_or_adjust(s, C::zero());
while let Some((u, w)) = heap.pop() {
assert!(w == dis[u]);
for (i, e) in graph[u].iter().enumerate() {
let v = e.to();
debug_assert!(e.capacity() <= C::zero() || c(u, e, p) >= C::zero());
if e.capacity() > C::zero() && dis[v] > w + c(u, e, p) {
dis[v] = w + c(u, e, p);
pre[v] = (u, i);
heap.add_or_adjust(v, dis[v]);
}
}
}
};
let mut add_one =
|graph: &mut Graph<WeightedFlowEdgeRaw<C, C, Id, ()>>, from: usize, id: usize| {
if graph[from][id].capacity() > C::zero() {
*graph[from][id].capacity_mut() += C::one();
return;
}
let mut u = from;
let e = &graph[from][id];
let v = e.to();
let cur_len = c(u, e, &p);
dijkstra(graph, &mut dis, &mut pre, &mut heap, &p, v);
let e = &graph[from][id];
if dis[u] < inf && dis[u] + c(u, e, &p) < C::zero() {
let rev_id = e.reverse_id();
*graph[v][rev_id].capacity_mut() += C::one();
while u != v {
graph.push_flow(graph[pre[u].0][pre[u].1].push_flow(C::one()));
u = pre[u].0;
}
} else {
*graph[from][id].capacity_mut() += C::one();
}
let mut max_dis = C::zero();
for i in dis.iter().take(n) {
if *i != inf {
max_dis.maxim(*i);
}
}
for i in 0..n {
p[i] += if dis[i] < inf {
dis[i]
} else {
max_dis
+ if cur_len > C::zero() {
cur_len
} else {
C::zero() - cur_len
}
};
}
dijkstra(graph, &mut dis, &mut pre, &mut heap, &p, n);
for i in 0..n {
let npi = dis[i] - p[n];
p[i] += npi;
}
};
add_one(&mut graph, sink, back);
for i in (0..bits).rev() {
for j in 0..=n {
for e in graph[j].iter_mut() {
*e.capacity_mut() <<= 1;
}
}
for (from, self_edge_id, graph_edge_id) in corresponding.iter() {
if or_graph[*from][*self_edge_id].capacity().is_set(i) {
add_one(&mut graph, *from, *graph_edge_id);
if graph[sink][back].capacity() == C::one() {
*graph[sink][back].capacity_mut() += C::one();
}
}
}
}
let mut min_cost = C::zero();
let max_flow = graph[sink][back].flow(&graph);
for (from, self_edge_id, graph_edge_id) in corresponding {
let x = &graph[from][graph_edge_id];
min_cost += x.flow(&graph) * x.weight();
or_graph.push_flow(or_graph[from][self_edge_id].push_flow(x.flow(&graph)));
}
CostAndFlow {
cost: min_cost,
flow: max_flow,
}
}
impl<C, Id, P: Clone + Default> MinCostFlow<C> for Graph<WeightedFlowEdgeRaw<C, C, Id, P>>
where
C: Ring + Ord + Copy + MinMax + Bits + Display,
Id: EdgeId,
{
fn min_cost_flow(&mut self, source: usize, sink: usize) -> CostAndFlow<C> {
min_cost_flow_impl(self, source, sink, false)
}
fn min_cost_max_flow(&mut self, source: usize, sink: usize) -> CostAndFlow<C> {
min_cost_flow_impl(self, source, sink, true)
}
}
}
}
pub mod io {
pub mod input {
use crate::algo_lib::collections::vec_ext::default::default_vec;
use std::io::Read;
use std::mem::MaybeUninit;
pub struct Input<'s> {
input: &'s mut (dyn Read + Send),
buf: Vec<u8>,
at: usize,
buf_read: usize,
}
macro_rules! read_impl {
($t: ty, $read_name: ident, $read_vec_name: ident) => {
pub fn $read_name(&mut self) -> $t {
self.read()
}
pub fn $read_vec_name(&mut self, len: usize) -> Vec<$t> {
self.read_vec(len)
}
};
($t: ty, $read_name: ident, $read_vec_name: ident, $read_pair_vec_name: ident) => {
read_impl!($t, $read_name, $read_vec_name);
pub fn $read_pair_vec_name(&mut self, len: usize) -> Vec<($t, $t)> {
self.read_vec(len)
}
};
}
impl<'s> Input<'s> {
const DEFAULT_BUF_SIZE: usize = 4096;
pub fn new(input: &'s mut (dyn Read + Send)) -> Self {
Self {
input,
buf: default_vec(Self::DEFAULT_BUF_SIZE),
at: 0,
buf_read: 0,
}
}
pub fn new_with_size(input: &'s mut (dyn Read + Send), buf_size: usize) -> Self {
Self {
input,
buf: default_vec(buf_size),
at: 0,
buf_read: 0,
}
}
pub fn get(&mut self) -> Option<u8> {
if self.refill_buffer() {
let res = self.buf[self.at];
self.at += 1;
if res == b'\r' {
if self.refill_buffer() && self.buf[self.at] == b'\n' {
self.at += 1;
}
return Some(b'\n');
}
Some(res)
} else {
None
}
}
pub fn peek(&mut self) -> Option<u8> {
if self.refill_buffer() {
let res = self.buf[self.at];
Some(if res == b'\r' { b'\n' } else { res })
} else {
None
}
}
pub fn skip_whitespace(&mut self) {
while let Some(b) = self.peek() {
if !b.is_ascii_whitespace() {
return;
}
self.get();
}
}
pub fn next_token(&mut self) -> Option<Vec<u8>> {
self.skip_whitespace();
let mut res = Vec::new();
while let Some(c) = self.get() {
if c.is_ascii_whitespace() {
break;
}
res.push(c);
}
if res.is_empty() {
None
} else {
Some(res)
}
}
//noinspection RsSelfConvention
pub fn is_exhausted(&mut self) -> bool {
self.peek().is_none()
}
//noinspection RsSelfConvention
pub fn is_empty(&mut self) -> bool {
self.skip_whitespace();
self.is_exhausted()
}
pub fn read<T: Readable>(&mut self) -> T {
T::read(self)
}
pub fn read_vec<T: Readable>(&mut self, size: usize) -> Vec<T> {
let mut res = Vec::with_capacity(size);
for _ in 0..size {
res.push(self.read());
}
res
}
pub fn read_char(&mut self) -> u8 {
self.skip_whitespace();
self.get().unwrap()
}
read_impl!(u32, read_unsigned, read_unsigned_vec);
read_impl!(u64, read_u64, read_u64_vec);
read_impl!(usize, read_size, read_size_vec, read_size_pair_vec);
read_impl!(i32, read_int, read_int_vec, read_int_pair_vec);
read_impl!(i64, read_long, read_long_vec, read_long_pair_vec);
read_impl!(i128, read_i128, read_i128_vec);
fn refill_buffer(&mut self) -> bool {
if self.at == self.buf_read {
self.at = 0;
self.buf_read = self.input.read(&mut self.buf).unwrap();
self.buf_read != 0
} else {
true
}
}
}
pub trait Readable {
fn read(input: &mut Input) -> Self;
}
impl Readable for u8 {
fn read(input: &mut Input) -> Self {
input.read_char()
}
}
impl<T: Readable> Readable for Vec<T> {
fn read(input: &mut Input) -> Self {
let size = input.read();
input.read_vec(size)
}
}
impl<T: Readable, const SIZE: usize> Readable for [T; SIZE] {
fn read(input: &mut Input) -> Self {
unsafe {
let mut res = MaybeUninit::<[T; SIZE]>::uninit();
for i in 0..SIZE {
let ptr: *mut T = (*res.as_mut_ptr()).as_mut_ptr();
ptr.add(i).write(input.read::<T>());
}
res.assume_init()
}
}
}
macro_rules! read_integer {
($($t:ident)+) => {$(
impl Readable for $t {
fn read(input: &mut Input) -> Self {
input.skip_whitespace();
let mut c = input.get().unwrap();
let sgn = match c {
b'-' => {
c = input.get().unwrap();
true
}
b'+' => {
c = input.get().unwrap();
false
}
_ => false,
};
let mut res = 0;
loop {
assert!(c.is_ascii_digit());
res *= 10;
let d = (c - b'0') as $t;
if sgn {
res -= d;
} else {
res += d;
}
match input.get() {
None => break,
Some(ch) => {
if ch.is_ascii_whitespace() {
break;
} else {
c = ch;
}
}
}
}
res
}
}
)+};
}
read_integer!(i8 i16 i32 i64 i128 isize u16 u32 u64 u128 usize);
macro_rules! tuple_readable {
($($name:ident)+) => {
impl<$($name: Readable), +> Readable for ($($name,)+) {
fn read(input: &mut Input) -> Self {
($($name::read(input),)+)
}
}
}
}
tuple_readable! {T}
tuple_readable! {T U}
tuple_readable! {T U V}
tuple_readable! {T U V X}
tuple_readable! {T U V X Y}
tuple_readable! {T U V X Y Z}
tuple_readable! {T U V X Y Z A}
tuple_readable! {T U V X Y Z A B}
tuple_readable! {T U V X Y Z A B C}
tuple_readable! {T U V X Y Z A B C D}
tuple_readable! {T U V X Y Z A B C D E}
tuple_readable! {T U V X Y Z A B C D E F}
impl Read for Input<'_> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
if self.at == self.buf_read {
self.input.read(buf)
} else {
let mut i = 0;
while i < buf.len() && self.at < self.buf_read {
buf[i] = self.buf[self.at];
i += 1;
self.at += 1;
}
Ok(i)
}
}
}
}
pub mod output {
use crate::algo_lib::collections::vec_ext::default::default_vec;
use std::cmp::Reverse;
use std::io::stderr;
use std::io::Stderr;
use std::io::Write;
#[derive(Copy, Clone)]
pub enum BoolOutput {
YesNo,
YesNoCaps,
PossibleImpossible,
Custom(&'static str, &'static str),
}
impl BoolOutput {
pub fn output(&self, output: &mut Output, val: bool) {
(if val { self.yes() } else { self.no() }).write(output);
}
fn yes(&self) -> &str {
match self {
BoolOutput::YesNo => "Yes",
BoolOutput::YesNoCaps => "YES",
BoolOutput::PossibleImpossible => "Possible",
BoolOutput::Custom(yes, _) => yes,
}
}
fn no(&self) -> &str {
match self {
BoolOutput::YesNo => "No",
BoolOutput::YesNoCaps => "NO",
BoolOutput::PossibleImpossible => "Impossible",
BoolOutput::Custom(_, no) => no,
}
}
}
pub struct Output<'s> {
output: &'s mut dyn Write,
buf: Vec<u8>,
at: usize,
auto_flush: bool,
bool_output: BoolOutput,
precision: Option<usize>,
}
impl<'s> Output<'s> {
const DEFAULT_BUF_SIZE: usize = 4096;
pub fn new(output: &'s mut dyn Write) -> Self {
Self {
output,
buf: default_vec(Self::DEFAULT_BUF_SIZE),
at: 0,
auto_flush: false,
bool_output: BoolOutput::YesNoCaps,
precision: None,
}
}
pub fn new_with_auto_flush(output: &'s mut dyn Write) -> Self {
Self {
output,
buf: default_vec(Self::DEFAULT_BUF_SIZE),
at: 0,
auto_flush: true,
bool_output: BoolOutput::YesNoCaps,
precision: None,
}
}
pub fn flush(&mut self) {
if self.at != 0 {
self.output.write_all(&self.buf[..self.at]).unwrap();
self.output.flush().unwrap();
self.at = 0;
}
}
pub fn print<T: Writable>(&mut self, s: T) {
s.write(self);
self.maybe_flush();
}
pub fn print_line<T: Writable>(&mut self, s: T) {
self.print(s);
self.put(b'\n');
self.maybe_flush();
}
pub fn put(&mut self, b: u8) {
self.buf[self.at] = b;
self.at += 1;
if self.at == self.buf.len() {
self.flush();
}
}
pub fn maybe_flush(&mut self) {
if self.auto_flush {
self.flush();
}
}
pub fn print_per_line<T: Writable>(&mut self, arg: &[T]) {
self.print_per_line_iter(arg.iter());
}
pub fn print_iter<T: Writable, I: Iterator<Item = T>>(&mut self, iter: I) {
let mut first = true;
for e in iter {
if first {
first = false;
} else {
self.put(b' ');
}
e.write(self);
}
}
pub fn print_line_iter<T: Writable, I: Iterator<Item = T>>(&mut self, iter: I) {
self.print_iter(iter);
self.put(b'\n');
}
pub fn print_per_line_iter<T: Writable, I: Iterator<Item = T>>(&mut self, iter: I) {
for e in iter {
e.write(self);
self.put(b'\n');
}
}
pub fn set_bool_output(&mut self, bool_output: BoolOutput) {
self.bool_output = bool_output;
}
pub fn set_precision(&mut self, precision: Option<usize>) {
self.precision = precision;
}
pub fn get_precision(&self) -> Option<usize> {
self.precision
}
}
impl Write for Output<'_> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let mut start = 0usize;
let mut rem = buf.len();
while rem > 0 {
let len = (self.buf.len() - self.at).min(rem);
self.buf[self.at..self.at + len].copy_from_slice(&buf[start..start + len]);
self.at += len;
if self.at == self.buf.len() {
self.flush();
}
start += len;
rem -= len;
}
self.maybe_flush();
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
self.flush();
Ok(())
}
}
pub trait Writable {
fn write(&self, output: &mut Output);
}
impl Writable for &str {
fn write(&self, output: &mut Output) {
output.write_all(self.as_bytes()).unwrap();
}
}
impl Writable for String {
fn write(&self, output: &mut Output) {
output.write_all(self.as_bytes()).unwrap();
}
}
impl Writable for char {
fn write(&self, output: &mut Output) {
output.put(*self as u8);
}
}
impl Writable for u8 {
fn write(&self, output: &mut Output) {
output.put(*self);
}
}
impl<T: Writable> Writable for [T] {
fn write(&self, output: &mut Output) {
output.print_iter(self.iter());
}
}
impl<T: Writable, const N: usize> Writable for [T; N] {
fn write(&self, output: &mut Output) {
output.print_iter(self.iter());
}
}
impl<T: Writable + ?Sized> Writable for &T {
fn write(&self, output: &mut Output) {
T::write(self, output)
}
}
impl<T: Writable> Writable for Vec<T> {
fn write(&self, output: &mut Output) {
self.as_slice().write(output);
}
}
impl Writable for () {
fn write(&self, _output: &mut Output) {}
}
macro_rules! write_to_string {
($($t:ident)+) => {$(
impl Writable for $t {
fn write(&self, output: &mut Output) {
self.to_string().write(output);
}
}
)+};
}
write_to_string!(u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
macro_rules! tuple_writable {
($name0:ident $($name:ident: $id:tt )*) => {
impl<$name0: Writable, $($name: Writable,)*> Writable for ($name0, $($name,)*) {
fn write(&self, out: &mut Output) {
self.0.write(out);
$(
out.put(b' ');
self.$id.write(out);
)*
}
}
}
}
tuple_writable! {T}
tuple_writable! {T U:1}
tuple_writable! {T U:1 V:2}
tuple_writable! {T U:1 V:2 X:3}
tuple_writable! {T U:1 V:2 X:3 Y:4}
tuple_writable! {T U:1 V:2 X:3 Y:4 Z:5}
tuple_writable! {T U:1 V:2 X:3 Y:4 Z:5 A:6}
tuple_writable! {T U:1 V:2 X:3 Y:4 Z:5 A:6 B:7}
tuple_writable! {T U:1 V:2 X:3 Y:4 Z:5 A:6 B:7 C:8}
impl<T: Writable> Writable for Option<T> {
fn write(&self, output: &mut Output) {
match self {
None => (-1).write(output),
Some(t) => t.write(output),
}
}
}
impl Writable for bool {
fn write(&self, output: &mut Output) {
let bool_output = output.bool_output;
bool_output.output(output, *self)
}
}
impl<T: Writable> Writable for Reverse<T> {
fn write(&self, output: &mut Output) {
self.0.write(output);
}
}
static mut ERR: Option<Stderr> = None;
pub fn err() -> Output<'static> {
unsafe {
if ERR.is_none() {
ERR = Some(stderr());
}
Output::new_with_auto_flush(ERR.as_mut().unwrap())
}
}
}
}
pub mod misc {
pub mod test_type {
pub enum TestType {
Single,
MultiNumber,
MultiEof,
}
pub enum TaskType {
Classic,
Interactive,
}
}
}
pub mod numbers {
pub mod num_traits {
pub mod algebra {
use crate::algo_lib::numbers::num_traits::invertible::Invertible;
use std::ops::Add;
use std::ops::AddAssign;
use std::ops::Div;
use std::ops::DivAssign;
use std::ops::Mul;
use std::ops::MulAssign;
use std::ops::Neg;
use std::ops::Rem;
use std::ops::RemAssign;
use std::ops::Sub;
use std::ops::SubAssign;
pub trait Zero {
fn zero() -> Self;
}
pub trait One {
fn one() -> Self;
}
pub trait AdditionMonoid: Add<Output = Self> + AddAssign + Zero + Eq + Sized {}
impl<T: Add<Output = Self> + AddAssign + Zero + Eq> AdditionMonoid for T {}
pub trait AdditionMonoidWithSub: AdditionMonoid + Sub<Output = Self> + SubAssign {}
impl<T: AdditionMonoid + Sub<Output = Self> + SubAssign> AdditionMonoidWithSub for T {}
pub trait AdditionGroup: AdditionMonoidWithSub + Neg<Output = Self> {}
impl<T: AdditionMonoidWithSub + Neg<Output = Self>> AdditionGroup for T {}
pub trait MultiplicationMonoid: Mul<Output = Self> + MulAssign + One + Eq + Sized {}
impl<T: Mul<Output = Self> + MulAssign + One + Eq> MultiplicationMonoid for T {}
pub trait IntegerMultiplicationMonoid:
MultiplicationMonoid + Div<Output = Self> + Rem<Output = Self> + DivAssign + RemAssign
{
}
impl<T: MultiplicationMonoid + Div<Output = Self> + Rem<Output = Self> + DivAssign + RemAssign>
IntegerMultiplicationMonoid for T
{
}
pub trait MultiplicationGroup:
MultiplicationMonoid + Div<Output = Self> + DivAssign + Invertible<Output = Self>
{
}
impl<T: MultiplicationMonoid + Div<Output = Self> + DivAssign + Invertible<Output = Self>>
MultiplicationGroup for T
{
}
pub trait SemiRing: AdditionMonoid + MultiplicationMonoid {}
impl<T: AdditionMonoid + MultiplicationMonoid> SemiRing for T {}
pub trait SemiRingWithSub: AdditionMonoidWithSub + SemiRing {}
impl<T: AdditionMonoidWithSub + SemiRing> SemiRingWithSub for T {}
pub trait Ring: SemiRing + AdditionGroup {}
impl<T: SemiRing + AdditionGroup> Ring for T {}
pub trait IntegerSemiRing: SemiRing + IntegerMultiplicationMonoid {}
impl<T: SemiRing + IntegerMultiplicationMonoid> IntegerSemiRing for T {}
pub trait IntegerSemiRingWithSub: SemiRingWithSub + IntegerSemiRing {}
impl<T: SemiRingWithSub + IntegerSemiRing> IntegerSemiRingWithSub for T {}
pub trait IntegerRing: IntegerSemiRing + Ring {}
impl<T: IntegerSemiRing + Ring> IntegerRing for T {}
pub trait Field: Ring + MultiplicationGroup {}
impl<T: Ring + MultiplicationGroup> Field for T {}
macro_rules! zero_one_integer_impl {
($($t: ident)+) => {$(
impl Zero for $t {
fn zero() -> Self {
0
}
}
impl One for $t {
fn one() -> Self {
1
}
}
)+};
}
zero_one_integer_impl!(i128 i64 i32 i16 i8 isize u128 u64 u32 u16 u8 usize);
}
pub mod bit_ops {
use crate::algo_lib::numbers::num_traits::algebra::One;
use crate::algo_lib::numbers::num_traits::algebra::Zero;
use std::ops::BitAnd;
use std::ops::BitAndAssign;
use std::ops::BitOr;
use std::ops::BitOrAssign;
use std::ops::BitXor;
use std::ops::BitXorAssign;
use std::ops::Not;
use std::ops::RangeInclusive;
use std::ops::Shl;
use std::ops::Sub;
use std::ops::ShlAssign;
use std::ops::Shr;
use std::ops::ShrAssign;
pub trait BitOps:
Copy
+ BitAnd<Output = Self>
+ BitAndAssign
+ BitOr<Output = Self>
+ BitOrAssign
+ BitXor<Output = Self>
+ BitXorAssign
+ Not<Output = Self>
+ Shl<usize, Output = Self>
+ ShlAssign<usize>
+ Shr<usize, Output = Self>
+ ShrAssign<usize>
+ Zero
+ One
+ PartialEq
{
#[inline]
fn bit(at: usize) -> Self {
Self::one() << at
}
#[inline]
fn is_set(&self, at: usize) -> bool {
(*self >> at & Self::one()) == Self::one()
}
#[inline]
fn set_bit(&mut self, at: usize) {
*self |= Self::bit(at)
}
#[inline]
fn unset_bit(&mut self, at: usize) {
*self &= !Self::bit(at)
}
#[must_use]
#[inline]
fn with_bit(mut self, at: usize) -> Self {
self.set_bit(at);
self
}
#[must_use]
#[inline]
fn without_bit(mut self, at: usize) -> Self {
self.unset_bit(at);
self
}
#[inline]
fn flip_bit(&mut self, at: usize) {
*self ^= Self::bit(at)
}
#[must_use]
#[inline]
fn flipped_bit(mut self, at: usize) -> Self {
self.flip_bit(at);
self
}
fn all_bits(n: usize) -> Self {
let mut res = Self::zero();
for i in 0..n {
res.set_bit(i);
}
res
}
fn iter_all(n: usize) -> RangeInclusive<Self> {
Self::zero()..=Self::all_bits(n)
}
}
pub struct BitIter<T> {
cur: T,
all: T,
ended: bool,
}
impl<T: Copy> BitIter<T> {
pub fn new(all: T) -> Self {
Self {
cur: all,
all,
ended: false,
}
}
}
impl<T: BitOps + Sub<Output = T>> Iterator for BitIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.ended {
return None;
}
let res = self.cur;
if self.cur == T::zero() {
self.ended = true;
} else {
self.cur = (self.cur - T::one()) & self.all;
}
Some(res)
}
}
impl<
T: Copy
+ BitAnd<Output = Self>
+ BitAndAssign
+ BitOr<Output = Self>
+ BitOrAssign
+ BitXor<Output = Self>
+ BitXorAssign
+ Not<Output = Self>
+ Shl<usize, Output = Self>
+ ShlAssign<usize>
+ Shr<usize, Output = Self>
+ ShrAssign<usize>
+ One
+ Zero
+ PartialEq,
> BitOps for T
{
}
pub trait Bits: BitOps {
fn bits() -> u32;
}
macro_rules! bits_integer_impl {
($($t: ident $bits: expr),+) => {$(
impl Bits for $t {
fn bits() -> u32 {
$bits
}
}
)+};
}
bits_integer_impl!(i128 128, i64 64, i32 32, i16 16, i8 8, isize 64, u128 128, u64 64, u32 32, u16 16, u8 8, usize 64);
}
pub mod invertible {
pub trait Invertible {
type Output;
fn inv(&self) -> Option<Self::Output>;
}
}
pub mod ord {
pub trait MinMax: PartialOrd {
fn min_val() -> Self;
fn max_val() -> Self;
}
macro_rules! min_max_integer_impl {
($($t: ident)+) => {$(
impl MinMax for $t {
fn min_val() -> Self {
// 1.43
std::$t::MIN
}
fn max_val() -> Self {
// 1.43
std::$t::MAX
}
}
)+};
}
min_max_integer_impl!(i128 i64 i32 i16 i8 isize u128 u64 u32 u16 u8 usize);
}
}
}
pub mod string {
pub mod str {
use crate::algo_lib::collections::iter_ext::collect::IterCollect;
use crate::algo_lib::collections::slice_ext::backward::Back;
use crate::algo_lib::io::input::Input;
use crate::algo_lib::io::input::Readable;
use crate::algo_lib::io::output::Output;
use crate::algo_lib::io::output::Writable;
use std::cmp::Ordering;
use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::Formatter;
use std::hash::Hash;
use std::hash::Hasher;
use std::iter::Copied;
use std::iter::FromIterator;
use std::marker::PhantomData;
use std::ops::Add;
use std::ops::AddAssign;
use std::ops::Deref;
use std::ops::DerefMut;
use std::ops::Index;
use std::ops::IndexMut;
use std::ops::RangeBounds;
use std::slice::Iter;
use std::slice::IterMut;
use std::slice::SliceIndex;
use std::str::FromStr;
use std::vec::IntoIter;
pub enum Str<'s> {
Extendable(Vec<u8>, PhantomData<&'s [u8]>),
Owned(Box<[u8]>, PhantomData<&'s [u8]>),
Ref(&'s [u8]),
}
impl<'s> Str<'s> {
pub fn substr(&self, range: impl RangeBounds<usize>) -> Str {
let from = match range.start_bound() {
std::ops::Bound::Included(&i) => i,
std::ops::Bound::Excluded(&i) => i + 1,
std::ops::Bound::Unbounded => 0,
};
let to = match range.end_bound() {
std::ops::Bound::Included(&i) => i + 1,
std::ops::Bound::Excluded(&i) => i,
std::ops::Bound::Unbounded => self.len(),
};
Str::from(&self[from..to])
}
}
impl Default for Str<'static> {
fn default() -> Self {
Self::new()
}
}
impl Str<'static> {
pub fn new() -> Self {
Str::Extendable(Vec::new(), PhantomData)
}
pub fn with_capacity(cap: usize) -> Self {
Str::Extendable(Vec::with_capacity(cap), PhantomData)
}
}
impl<'s> Str<'s> {
pub fn push(&mut self, c: u8) {
self.transform_to_extendable();
self.as_extendable().push(c)
}
pub fn pop(&mut self) -> Option<u8> {
self.transform_to_extendable();
self.as_extendable().pop()
}
pub fn as_slice(&self) -> &[u8] {
match self {
Str::Extendable(s, _) => s.as_ref(),
Str::Owned(s, _) => s.as_ref(),
Str::Ref(s) => s,
}
}
pub fn len(&self) -> usize {
self.as_slice().len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn resize(&mut self, new_len: usize, value: u8) {
self.transform_to_extendable();
self.as_extendable().resize(new_len, value);
}
pub fn iter(&self) -> Copied<Iter<u8>> {
match self {
Str::Extendable(v, _) => v.iter(),
Str::Owned(v, _) => v.iter(),
Str::Ref(v) => v.iter(),
}
.copied()
}
pub fn iter_mut(&mut self) -> IterMut<u8> {
self.transform_to_owned();
self.as_mut_slice().iter_mut()
}
pub fn sort(&mut self) {
self.transform_to_owned();
self.as_mut_slice().sort_unstable();
}
pub fn into_owned(mut self) -> Str<'static> {
self.transform_to_owned();
match self {
Str::Extendable(v, _) => Str::Extendable(v, PhantomData),
Str::Owned(v, _) => Str::Owned(v, PhantomData),
_ => unreachable!(),
}
}
fn transform_to_extendable(&mut self) {
match self {
Str::Extendable(_, _) => {}
Str::Owned(_, _) => {
let mut fake = Str::new();
std::mem::swap(self, &mut fake);
if let Str::Owned(s, _) = fake {
*self = Str::Extendable(s.into_vec(), PhantomData)
} else {
unreachable!();
}
}
Str::Ref(s) => *self = Str::Extendable(s.to_vec(), PhantomData),
}
}
fn as_extendable(&mut self) -> &mut Vec<u8> {
match self {
Str::Extendable(s, _) => s,
_ => panic!("unreachable"),
}
}
fn transform_to_owned(&mut self) {
if let Str::Ref(s) = self {
*self = Str::Owned(s.to_vec().into_boxed_slice(), PhantomData)
}
}
pub fn as_mut_slice(&mut self) -> &mut [u8] {
self.transform_to_owned();
match self {
Str::Extendable(s, _) => s.as_mut_slice(),
Str::Owned(s, _) => s.as_mut(),
_ => panic!("unreachable"),
}
}
pub fn into_string(self) -> String {
match self {
Str::Extendable(v, _) => unsafe { String::from_utf8_unchecked(v) },
Str::Owned(v, _) => unsafe { String::from_utf8_unchecked(v.into_vec()) },
Str::Ref(v) => String::from_utf8_lossy(v).into_owned(),
}
}
pub fn reverse(&mut self) {
self.as_mut_slice().reverse();
}
pub fn trim(&self) -> Str<'_> {
let mut start = 0;
let mut end = self.len();
while start < end && (self[start] as char).is_whitespace() {
start += 1;
}
while start < end && (self[end - 1] as char).is_whitespace() {
end -= 1;
}
self[start..end].into()
}
pub fn split<'a, 'b>(&'a self, sep: impl Into<Str<'b>>) -> Vec<Str<'a>>
where
's: 'a,
{
let sep = sep.into();
let mut res = Vec::new();
let mut start = 0;
for i in 0..self.len() {
if self[i..].starts_with(sep.as_slice()) {
res.push(self[start..i].into());
start = i + sep.len();
}
}
res.push(self[start..].into());
res
}
pub fn parse<F: FromStr>(self) -> F
where
F::Err: Debug,
{
self.into_string().parse().unwrap()
}
pub fn parse_vec<T: Readable>(&self) -> Vec<T> {
let mut bytes = self.as_slice();
let mut input = Input::new(&mut bytes);
let mut res = Vec::new();
while !input.is_exhausted() {
res.push(input.read());
}
res
}
pub fn qty(&self, from: u8, to: u8) -> Vec<usize> {
let mut res = vec![0; (to - from + 1) as usize];
for &c in self.as_slice() {
res[(c - from) as usize] += 1;
}
res
}
pub fn qty_lower(&self) -> Vec<usize> {
self.qty(b'a', b'z')
}
}
impl<'s> IntoIterator for Str<'s> {
type Item = u8;
type IntoIter = IntoIter<u8>;
#[allow(clippy::unnecessary_to_owned)]
fn into_iter(self) -> Self::IntoIter {
match self {
Str::Extendable(v, _) => v.into_iter(),
Str::Owned(v, _) => v.into_vec().into_iter(),
Str::Ref(v) => v.to_vec().into_iter(),
}
}
}
impl From<String> for Str<'static> {
fn from(s: String) -> Self {
Str::Extendable(s.into(), PhantomData)
}
}
impl<'s> From<&'s str> for Str<'s> {
fn from(s: &'s str) -> Self {
Str::Ref(s.as_bytes())
}
}
impl From<Vec<u8>> for Str<'static> {
fn from(s: Vec<u8>) -> Self {
Str::Extendable(s, PhantomData)
}
}
impl<'s> From<&'s [u8]> for Str<'s> {
fn from(s: &'s [u8]) -> Self {
Str::Ref(s)
}
}
impl<'s, const N: usize> From<&'s [u8; N]> for Str<'s> {
fn from(s: &'s [u8; N]) -> Self {
Str::Ref(s)
}
}
impl<'s> From<&'s String> for Str<'s> {
fn from(s: &'s String) -> Self {
Str::Ref(s.as_bytes())
}
}
impl<'s> From<&'s Vec<u8>> for Str<'s> {
fn from(s: &'s Vec<u8>) -> Self {
Str::Ref(s.as_slice())
}
}
impl From<u8> for Str<'static> {
fn from(c: u8) -> Self {
Str::Owned(Box::new([c]), PhantomData)
}
}
impl From<char> for Str<'static> {
fn from(c: char) -> Self {
Str::from(c as u8)
}
}
impl<'s, 't: 's> From<&'s Str<'t>> for Str<'s> {
fn from(value: &'s Str<'t>) -> Self {
Str::Ref(value.as_slice())
}
}
impl<R: SliceIndex<[u8]>> Index<R> for Str<'_> {
type Output = R::Output;
fn index(&self, index: R) -> &Self::Output {
self.as_slice().index(index)
}
}
impl<R: SliceIndex<[u8]>> IndexMut<R> for Str<'_> {
fn index_mut(&mut self, index: R) -> &mut Self::Output {
self.transform_to_owned();
self.as_mut_slice().index_mut(index)
}
}
impl Clone for Str<'_> {
fn clone(&self) -> Self {
match self {
Str::Extendable(s, _) => s.clone().into(),
Str::Owned(s, _) => s.to_vec().into(),
Str::Ref(s) => Str::Ref(s),
}
}
}
impl<'r, 's, S: Into<Str<'r>>> AddAssign<S> for Str<'s> {
fn add_assign(&mut self, rhs: S) {
self.transform_to_extendable();
self.as_extendable()
.extend_from_slice(rhs.into().as_slice());
}
}
impl<'r, 's, S: Into<Str<'r>>> Add<S> for Str<'s> {
type Output = Str<'s>;
fn add(mut self, rhs: S) -> Self::Output {
self += rhs;
self
}
}
impl Readable for Str<'static> {
fn read(input: &mut Input) -> Self {
input.next_token().unwrap().into()
}
}
impl Writable for Str<'_> {
fn write(&self, output: &mut Output) {
for c in self.as_slice() {
output.put(*c);
}
output.maybe_flush();
}
}
impl Display for Str<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
<String as Display>::fmt(&String::from_utf8(self.as_slice().to_vec()).unwrap(), f)
}
}
impl Hash for Str<'_> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_slice().hash(state);
}
}
impl<'r> PartialEq<Str<'r>> for Str<'_> {
fn eq(&self, other: &Str<'r>) -> bool {
self.as_slice().eq(other.as_slice())
}
}
impl Eq for Str<'_> {}
impl<'r> PartialOrd<Str<'r>> for Str<'_> {
fn partial_cmp(&self, other: &Str<'r>) -> Option<Ordering> {
self.as_slice().partial_cmp(other.as_slice())
}
}
impl Ord for Str<'_> {
fn cmp(&self, other: &Self) -> Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl FromIterator<u8> for Str<'static> {
fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
Self::Extendable(iter.into_iter().collect_vec(), Default::default())
}
}
impl<'r> FromIterator<&'r u8> for Str<'static> {
fn from_iter<T: IntoIterator<Item = &'r u8>>(iter: T) -> Self {
Self::Extendable(iter.into_iter().cloned().collect_vec(), Default::default())
}
}
impl Deref for Str<'_> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl DerefMut for Str<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut_slice()
}
}
pub trait StrReader {
fn read_str(&mut self) -> Str<'static>;
fn read_str_vec(&mut self, n: usize) -> Vec<Str<'static>>;
fn read_line(&mut self) -> Str<'static>;
fn read_line_vec(&mut self, n: usize) -> Vec<Str<'static>>;
fn read_lines(&mut self) -> Vec<Str<'static>>;
}
impl StrReader for Input<'_> {
fn read_str(&mut self) -> Str<'static> {
self.read()
}
fn read_str_vec(&mut self, n: usize) -> Vec<Str<'static>> {
self.read_vec(n)
}
fn read_line(&mut self) -> Str<'static> {
let mut res = Str::new();
while let Some(c) = self.get() {
if c == b'\n' {
break;
}
res.push(c);
}
res
}
fn read_line_vec(&mut self, n: usize) -> Vec<Str<'static>> {
let mut res = Vec::with_capacity(n);
for _ in 0..n {
res.push(self.read_line());
}
res
}
fn read_lines(&mut self) -> Vec<Str<'static>> {
let mut res = Vec::new();
while !self.is_exhausted() {
res.push(self.read_line());
}
if let Some(s) = res.last() {
if s.is_empty() {
res.pop();
}
}
res
}
}
impl Index<Back> for Str<'_> {
type Output = u8;
fn index(&self, index: Back) -> &Self::Output {
&self[self.len() - index.0 - 1]
}
}
impl IndexMut<Back> for Str<'_> {
fn index_mut(&mut self, index: Back) -> &mut Self::Output {
let len = self.len();
&mut self[len - index.0 - 1]
}
}
impl AsRef<[u8]> for Str<'_> {
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
}
}
}
fn main() {
let mut sin = std::io::stdin();
let input = algo_lib::io::input::Input::new(&mut sin);
let mut stdout = std::io::stdout();
let output = algo_lib::io::output::Output::new(&mut stdout);
solution::run(input, output);
}
詳細信息
Test #1:
score: 100
Accepted
time: 0ms
memory: 2260kb
input:
5 automated teller machine active teller machine active trouble maker always telling misinformation American Teller Machinery
output:
atm actm atma atem ATM
result:
ok len=18
Test #2:
score: 0
Accepted
time: 0ms
memory: 2276kb
input:
5 Forest Conservation Committee Forum Fuming Corruption Collusion Federation Fulsome Cash Concealment Foundation Funky Crony Capitalism Facilitator Funny Cocky Cocky Funny
output:
FCCoF FCCF FCaCF FCrCF FCCFu
result:
ok len=24
Test #3:
score: 0
Accepted
time: 0ms
memory: 2240kb
input:
3 A AA AA A A A A
output:
no solution
result:
ok len=-1
Test #4:
score: 0
Accepted
time: 0ms
memory: 2240kb
input:
2 QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnmertyuiop Q W E R T Y U I O P A S D F G H J K L Z X C V B N M q w e r t y u i o p a s d f g h j k l z x c v b n m j k l z x c v b n m
output:
Q QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnmjklzxcvbnm
result:
ok len=63
Test #5:
score: 0
Accepted
time: 0ms
memory: 2284kb
input:
10 aaa aaa aaa aaa aaa aaa aab aaa aaa aaa aaa aaa aaa aab aaa aaa aaa aaa aab aab aaa aaa aaa aaa a a a a a a ab ab a a a a a a ab ab b a a a a a a aw a a a a a az az a a a a az a a a a a
output:
aaaaaaa aabaaaaa aaabaaaa aaaaaaaa aaaaaa abaaaaaaa aabaaaaaa awaaaaa aazaaaa azaaaaa
result:
ok len=76
Test #6:
score: -100
Time Limit Exceeded
input:
128 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...