結果
| 問題 | No.3295 Buying Bottled Water |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-12-09 00:18:00 |
| 言語 | Rust (1.83.0 + proconio) |
| 結果 |
AC
|
| 実行時間 | 502 ms / 2,000 ms |
| コード長 | 16,249 bytes |
| 記録 | |
| コンパイル時間 | 12,915 ms |
| コンパイル使用メモリ | 397,660 KB |
| 実行使用メモリ | 7,852 KB |
| 最終ジャッジ日時 | 2025-12-09 00:18:17 |
| 合計ジャッジ時間 | 17,250 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 19 |
コンパイルメッセージ
warning: unused variable: `line`
--> src/main.rs:372:14
|
372 | fn show1d<T>(line: &[T])
| ^^^^ help: if this is intentional, prefix it with an underscore: `_line`
|
= note: `#[warn(unused_variables)]` on by default
warning: unused variable: `table2d`
--> src/main.rs:431:14
|
431 | fn show2d<T>(table2d: &[Vec<T>])
| ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_table2d`
ソースコード
#![allow(unused_macros, unused_imports, dead_code)]
use std::cmp::{max, min, Ordering, Reverse};
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
use std::mem::swap;
use std::ops::{
Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
};
use std::time::Instant;
macro_rules! __debug_impl {
($x:expr) => {
eprint!("{}={:?} ", stringify!($x), &$x);
};
($x:expr, $($y:expr),+) => (
__debug_impl!($x);
__debug_impl!($($y),+);
);
}
macro_rules! __debug_line {
() => {
eprint!("L{} ", line!());
};
}
macro_rules! __debug_select {
() => {
eprintln!();
};
($x:expr) => {
__debug_line!();
__debug_impl!($x);
eprintln!();
};
($x:expr, $($y:expr),+) => (
__debug_line!();
__debug_impl!($x);
__debug_impl!($($y),+);
eprintln!();
);
}
macro_rules! debug {
() => {
if cfg!(debug_assertions) {
__debug_select!();
}
};
($($xs:expr),+) => {
if cfg!(debug_assertions) {
__debug_select!($($xs),+);
}
};
}
mod change_min_max {
pub trait ChangeMinMax<T> {
fn chmin(&mut self, rhs: T) -> bool;
fn chmax(&mut self, rhs: T) -> bool;
}
impl<T: PartialOrd> ChangeMinMax<T> for T {
#[inline(always)]
fn chmin(&mut self, rhs: T) -> bool {
if *self > rhs {
*self = rhs;
true
} else {
false
}
}
#[inline(always)]
fn chmax(&mut self, rhs: T) -> bool {
if *self < rhs {
*self = rhs;
true
} else {
false
}
}
}
impl<T: Clone + PartialOrd> ChangeMinMax<T> for Option<T> {
#[inline(always)]
fn chmin(&mut self, rhs: T) -> bool {
if let Some(val) = self.clone() {
if val > rhs {
*self = Some(rhs);
true
} else {
false
}
} else {
*self = Some(rhs);
true
}
}
#[inline(always)]
fn chmax(&mut self, rhs: T) -> bool {
if let Some(val) = self.clone() {
if val < rhs {
*self = Some(rhs);
true
} else {
false
}
} else {
*self = Some(rhs);
true
}
}
}
}
use change_min_max::ChangeMinMax;
pub trait CoordinateCompress<T> {
fn compress_encoder(&self) -> HashMap<T, usize>;
fn compress_decoder(&self) -> Vec<T>;
fn compress(self) -> Vec<usize>;
}
impl<T: Copy + Ord + std::hash::Hash> CoordinateCompress<T> for Vec<T> {
fn compress_encoder(&self) -> HashMap<T, usize> {
let mut dict = BTreeSet::new();
for &x in self.iter() {
dict.insert(x);
}
let mut ret = HashMap::new();
for (i, value) in dict.into_iter().enumerate() {
ret.insert(value, i);
}
ret
}
fn compress_decoder(&self) -> Vec<T> {
let mut keys = BTreeSet::<T>::new();
for &x in self.iter() {
keys.insert(x);
}
keys.into_iter().collect::<Vec<T>>()
}
fn compress(self) -> Vec<usize> {
let dict = self.compress_encoder();
self.into_iter().map(|x| dict[&x]).collect::<Vec<usize>>()
}
}
impl<T: Copy + Ord + std::hash::Hash> CoordinateCompress<T> for BTreeSet<T> {
fn compress_encoder(&self) -> HashMap<T, usize> {
let mut dict = HashMap::new();
for (i, &key) in self.iter().enumerate() {
dict.insert(key, i);
}
dict
}
fn compress_decoder(&self) -> Vec<T> {
self.iter().copied().collect::<Vec<T>>()
}
fn compress(self) -> Vec<usize> {
(0..self.len()).collect::<Vec<usize>>()
}
}
impl<T: Copy + Ord + std::hash::Hash> CoordinateCompress<T> for HashSet<T> {
fn compress_encoder(&self) -> HashMap<T, usize> {
let mut dict = BTreeSet::new();
for &x in self.iter() {
dict.insert(x);
}
let mut ret = HashMap::new();
for (i, value) in dict.into_iter().enumerate() {
ret.insert(value, i);
}
ret
}
fn compress_decoder(&self) -> Vec<T> {
let mut keys = BTreeSet::<T>::new();
for &x in self.iter() {
keys.insert(x);
}
keys.into_iter().collect::<Vec<T>>()
}
fn compress(self) -> Vec<usize> {
let dict = self.compress_encoder();
self.into_iter().map(|x| dict[&x]).collect::<Vec<usize>>()
}
}
mod sort_vec_binary_search {
static mut VEC_IS_SORTED_ONCE: bool = false;
#[allow(clippy::type_complexity)]
fn sorted_binary_search<'a, T: PartialOrd>(
vec: &'a [T],
key: &T,
earlier: fn(&T, &T) -> bool,
) -> (Option<(usize, &'a T)>, Option<(usize, &'a T)>) {
unsafe {
if !VEC_IS_SORTED_ONCE {
for i in 1..vec.len() {
assert!(vec[i - 1] <= vec[i]);
}
VEC_IS_SORTED_ONCE = true;
}
}
if vec.is_empty() {
return (None, None);
}
if !earlier(&vec[0], key) {
(None, Some((0, &vec[0])))
} else if earlier(vec.last().unwrap(), key) {
(Some((vec.len() - 1, &vec[vec.len() - 1])), None)
} else {
let mut l = 0;
let mut r = vec.len() - 1;
while r - l > 1 {
let m = (l + r) / 2;
if earlier(&vec[m], key) {
l = m;
} else {
r = m;
}
}
(Some((l, &vec[l])), Some((r, &vec[r])))
}
}
pub trait SortVecBinarySearch<T> {
#[allow(clippy::type_complexity)]
fn greater_equal(&self, key: &T) -> Option<(usize, &T)>;
fn greater_than(&self, key: &T) -> Option<(usize, &T)>;
fn less_equal(&self, key: &T) -> Option<(usize, &T)>;
fn less_than(&self, key: &T) -> Option<(usize, &T)>;
}
impl<T: Ord> SortVecBinarySearch<T> for Vec<T> {
fn greater_equal(&self, key: &T) -> Option<(usize, &T)> {
sorted_binary_search(self, key, |x: &T, y: &T| x < y).1
}
fn greater_than(&self, key: &T) -> Option<(usize, &T)> {
sorted_binary_search(self, key, |x: &T, y: &T| x <= y).1
}
fn less_equal(&self, key: &T) -> Option<(usize, &T)> {
sorted_binary_search(self, key, |x: &T, y: &T| x <= y).0
}
fn less_than(&self, key: &T) -> Option<(usize, &T)> {
sorted_binary_search(self, key, |x: &T, y: &T| x < y).0
}
}
}
use sort_vec_binary_search::SortVecBinarySearch;
mod map_counter {
use std::cmp::Ord;
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
pub trait MapCounter<T> {
fn incr(&mut self, key: T) -> bool;
fn incr_by(&mut self, key: T, delta: usize) -> bool;
fn decr(&mut self, key: &T) -> bool;
fn decr_by(&mut self, key: &T, delta: usize) -> bool;
}
impl<T: Ord + Clone> MapCounter<T> for BTreeMap<T, usize> {
fn incr(&mut self, key: T) -> bool {
let stat0 = self.contains_key(&key);
self.incr_by(key.clone(), 1);
stat0 != self.contains_key(&key)
}
fn incr_by(&mut self, key: T, delta: usize) -> bool {
let stat0 = self.contains_key(&key);
*self.entry(key.clone()).or_insert(0) += delta;
stat0 != self.contains_key(&key)
}
fn decr(&mut self, key: &T) -> bool {
let stat0 = self.contains_key(key);
self.decr_by(key, 1);
stat0 != self.contains_key(key)
}
fn decr_by(&mut self, key: &T, delta: usize) -> bool {
let stat0 = self.contains_key(key);
let v = self.entry(key.clone()).or_insert(0);
debug_assert!(*v >= delta);
*v -= delta;
if *v == 0 {
self.remove(key);
}
stat0 != self.contains_key(key)
}
}
impl<T: Clone + Hash + Eq> MapCounter<T> for HashMap<T, usize> {
fn incr(&mut self, key: T) -> bool {
let stat0 = self.contains_key(&key);
self.incr_by(key.clone(), 1);
stat0 != self.contains_key(&key)
}
fn incr_by(&mut self, key: T, delta: usize) -> bool {
let stat0 = self.contains_key(&key);
*self.entry(key.clone()).or_insert(0) += delta;
stat0 != self.contains_key(&key)
}
fn decr(&mut self, key: &T) -> bool {
let stat0 = self.contains_key(key);
self.decr_by(key, 1);
stat0 != self.contains_key(key)
}
fn decr_by(&mut self, key: &T, delta: usize) -> bool {
let stat0 = self.contains_key(key);
let v = self.entry(key.clone()).or_insert(0);
debug_assert!(*v >= delta);
*v -= delta;
if *v == 0 {
self.remove(key);
}
stat0 != self.contains_key(key)
}
}
}
use map_counter::MapCounter;
mod usize_move_delta {
pub trait MoveDelta<T> {
fn move_delta(self, delta: T, lim_lo: usize, lim_hi: usize) -> Option<usize>;
}
impl<T: Copy + Into<i64>> MoveDelta<T> for usize {
fn move_delta(self, delta: T, lim_lo: usize, lim_hi: usize) -> Option<usize> {
let delta: i64 = delta.into();
let added: i64 = self as i64 + delta;
let lim_lo: i64 = lim_lo as i64;
let lim_hi: i64 = lim_hi as i64;
if (lim_lo <= added) && (added <= lim_hi) {
Some(added as usize)
} else {
None
}
}
}
}
use usize_move_delta::MoveDelta;
fn exit_by<T: std::fmt::Display>(msg: T) {
println!("{}", msg);
std::process::exit(0);
}
mod add_header {
pub trait AddHeader<T> {
fn add_header(&mut self, add_val: T);
}
impl<T> AddHeader<T> for Vec<T>
where
Vec<T>: Clone,
{
fn add_header(&mut self, add_val: T) {
let cpy = self.clone();
self.clear();
self.push(add_val);
for cpy_val in cpy {
self.push(cpy_val);
}
}
}
}
use add_header::AddHeader;
mod transpose {
pub trait Transpose<T> {
fn transpose(self) -> Vec<Vec<T>>;
}
impl<T: Clone> Transpose<T> for Vec<Vec<T>> {
fn transpose(self) -> Vec<Vec<T>> {
(0..self[0].len())
.map(|x| {
(0..self.len())
.map(|y| self[y][x].clone())
.collect::<Vec<_>>()
})
.collect::<Vec<_>>()
}
}
}
use transpose::Transpose;
fn show1d<T>(line: &[T])
where
T: std::fmt::Debug,
{
#[cfg(debug_assertions)]
{
use std::collections::VecDeque;
let ln = line.len();
let mx = line
.iter()
.map(|val| format!("{:?}", val).len())
.max()
.unwrap()
+ 2;
fn to_string<X>(x: X, mx: usize) -> String
where
X: std::fmt::Debug,
{
let mut s = format!("{:?}", x).chars().collect::<VecDeque<char>>();
let mut sw = 0;
while s.len() < mx {
if sw == 0 {
s.push_back(' ');
} else {
s.push_front(' ');
}
sw ^= 1;
}
s.into_iter().collect::<String>()
}
let eprintln_split = || {
eprint!("+");
for _ in 0..ln {
for _ in 0..mx {
eprint!("=");
}
eprint!("+");
}
eprintln!();
};
eprintln_split();
{
eprint!("|");
for x in 0..ln {
eprint!("{}", to_string::<usize>(x, mx));
eprint!("|");
}
eprintln!();
}
eprintln_split();
eprint!("|");
for val in line {
eprint!("{}|", to_string(val, mx));
}
eprintln!();
eprintln_split();
}
}
fn show2d<T>(table2d: &[Vec<T>])
where
T: std::fmt::Debug,
{
#[cfg(debug_assertions)]
{
use std::collections::VecDeque;
let w = table2d[0].len();
let mx = table2d
.iter()
.map(|line| {
line.iter()
.map(|val| format!("{:?}", val).len())
.max()
.unwrap()
})
.max()
.unwrap()
+ 2;
fn to_string<X>(x: X, mx: usize) -> String
where
X: std::fmt::Debug,
{
let mut s = format!("{:?}", x).chars().collect::<VecDeque<char>>();
let mut sw = 0;
while s.len() < mx {
if sw == 0 {
s.push_back(' ');
} else {
s.push_front(' ');
}
sw ^= 1;
}
s.into_iter().collect::<String>()
}
let eprintln_split = |doubled: bool| {
eprint!("+");
for _ in 0..=w {
for _ in 0..mx {
eprint!("{}", if doubled { '=' } else { '-' });
}
eprint!("+");
}
eprintln!();
};
eprintln_split(false);
{
eprint!("|");
for x in 0..=w {
let s = if x > 0 {
to_string::<usize>(x - 1, mx)
} else {
(0..mx).map(|_| ' ').collect::<String>()
};
eprint!("{s}");
eprint!("|");
}
eprintln!();
}
eprintln_split(true);
for (y, line) in table2d.iter().enumerate() {
eprint!("|");
eprint!("{}", to_string(y, mx));
eprint!("|");
for val in line {
eprint!("{}|", to_string(val, mx));
}
eprintln!();
eprintln_split(false);
}
}
}
mod procon_reader {
use std::fmt::Debug;
use std::io::Read;
use std::str::FromStr;
pub fn read<T: FromStr>() -> T
where
<T as FromStr>::Err: Debug,
{
let stdin = std::io::stdin();
let mut stdin_lock = stdin.lock();
let mut u8b: [u8; 1] = [0];
loop {
let mut buf: Vec<u8> = Vec::with_capacity(16);
loop {
let res = stdin_lock.read(&mut u8b);
if res.unwrap_or(0) == 0 || u8b[0] <= b' ' {
break;
} else {
buf.push(u8b[0]);
}
}
if !buf.is_empty() {
let ret = String::from_utf8(buf).unwrap();
return ret.parse().unwrap();
}
}
}
pub fn read_vec<T: std::str::FromStr>(n: usize) -> Vec<T>
where
<T as FromStr>::Err: Debug,
{
(0..n).map(|_| read::<T>()).collect::<Vec<T>>()
}
pub fn read_mat<T: std::str::FromStr>(h: usize, w: usize) -> Vec<Vec<T>>
where
<T as FromStr>::Err: Debug,
{
(0..h).map(|_| read_vec::<T>(w)).collect::<Vec<_>>()
}
}
use procon_reader::*;
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//#[proconio::fastout]
fn main() {
let n = read::<i64>();
let mut now = ((n + 500 - 1) / 500) * 500;
while now > 0 && n - (now - 1) * 500 < 100 {
now -= 1;
}
println!("{now}");
}