CSES - Putka Open 2020 – 2/5 - Results
Submission details
Task:Summat
Sender:Hennkka
Submission time:2020-09-26 14:33:18 +0300
Language:Rust
Status:READY
Result:100
Feedback
groupverdictscore
#1ACCEPTED12
#2ACCEPTED32
#3ACCEPTED56
Test results
testverdicttimegroup
#1ACCEPTED0.01 s1, 2, 3details
#2ACCEPTED0.01 s1, 2, 3details
#3ACCEPTED0.01 s1, 2, 3details
#4ACCEPTED0.01 s1, 2, 3details
#5ACCEPTED0.01 s1, 2, 3details
#6ACCEPTED0.01 s2, 3details
#7ACCEPTED0.01 s2, 3details
#8ACCEPTED0.01 s2, 3details
#9ACCEPTED0.01 s2, 3details
#10ACCEPTED0.01 s2, 3details
#11ACCEPTED0.01 s3details
#12ACCEPTED0.01 s3details
#13ACCEPTED0.04 s3details
#14ACCEPTED0.01 s3details
#15ACCEPTED0.01 s3details

Compiler report

warning: unused import: `std::collections::BTreeSet`
 --> input/code.rs:2:5
  |
2 | use std::collections::BTreeSet;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: unused variable: `n`
  --> input/code.rs:59:5
   |
59 |     n: usize,
   |     ^ help: consider prefixing with an underscore: `_n`
   |
   = note: `#[warn(unused_variables)]` on by default

Code

use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::io::BufRead;
fn print_iter<I: Iterator>(iter: I)
where
<I as Iterator>::Item: std::fmt::Display,
{
let mut iter = iter;
if let Some(v) = iter.next() {
print!("{}", v);
for v in iter {
print!(" {}", v);
}
}
println!();
}
struct Counter {
counts: BTreeMap<usize, usize>,
}
impl Counter {
pub fn new() -> Self {
Self {
counts: BTreeMap::new(),
}
}
pub fn is_empty(&self) -> bool {
self.counts.is_empty()
}
pub fn first(&self) -> usize {
*self.counts.iter().next().unwrap().0
}
pub fn add(&mut self, val: usize) {
*self.counts.entry(val).or_insert(0) += 1;
}
pub fn remove(&mut self, val: usize) -> bool {
let count = self.counts.get_mut(&val);
if let Some(count) = count {
assert!(*count > 0);
*count -= 1;
if *count == 0 {
self.counts.remove(&val);
}
true
} else {
false
}
}
}
fn solve_with_three_smallest(
v: &[usize],
n: usize,
(a0, a1, a2): (usize, usize, usize),
) -> Option<Vec<usize>> {
// println!("{}, {}, {}", a0, a1, a2);
// What to do with tree smallest elements?
let mut res = Vec::new();
let mut left = Counter::new();
for v in v {
left.add(*v);
}
left.remove(a0 + a1);
left.remove(a0 + a2);
left.remove(a1 + a2);
res.push(a0);
res.push(a1);
res.push(a2);
// The next smallest element has to be a0+??
while !left.is_empty() {
let ai = left.first() - a0;
for a in &res {
if !left.remove(a + ai) {
return None;
}
}
res.push(ai);
}
Some(res)
}
fn solve(v: Vec<usize>, n: usize) -> Vec<usize> {
assert_eq!(v.len(), n * (n - 1) / 2);
let mut v = v;
v.sort();
// Guess the three smallest elements
for i in 2..=(n + 3).min(v.len() - 1) {
let v0 = v[0];
let v1 = v[1];
let vi = v[i];
let a0 = (v0 + v1 - vi) / 2;
let a1 = (v0 + vi - v1) / 2;
let a2 = (v1 + vi - v0) / 2;
if a0 + a1 == v0 && a0 + a2 == v1 && a1 + a2 == vi {
if let Some(res) = solve_with_three_smallest(&v, n, (a0, a1, a2)) {
return res;
}
}
}
unreachable!()
// let v0 = v[0];
// let v1 = v[1];
// let v2 = v[2];
// let a0 = (v0 + v1 - v2) / 2;
// let a1 = (v0 + v2 - v1) / 2;
// let a2 = (v1 + v2 - v0) / 2;
// if a0 + a1 == v0 && a0 + a2 == v1 && a1 + a2 == v2 {
// solve_with_three_smallest(v, n, (a0, a1, a2)).unwrap()
// } else {
// todo!()
// }
// // Guess the three smallest elements
// let v0 = v[0];
// let v1 = v[1];
// let v2 = v[2];
// let a0 = (v0 + v1 - v2) / 2;
// let a1 = (v0 + v2 - v1) / 2;
// let a2 = (v1 + v2 - v0) / 2;
// if a0 + a1 == v0 && a0 + a2 == v1 && a1 + a2 == v2 {
// solve_with_three_smallest(v, n, (a0, a1, a2)).unwrap()
// } else {
// todo!()
// }
}
fn main() {
let stdin = std::io::stdin();
let stdin = stdin.lock();
let mut lines = stdin.lines();
let n: usize = lines.next().unwrap().unwrap().parse().unwrap();
let v = lines
.next()
.unwrap()
.unwrap()
.split_whitespace()
.map(|v| v.parse().unwrap())
.collect();
print_iter(solve(v, n).into_iter());
}
#[cfg(test)]
mod tests {
use super::*;
fn construct_input(v: &[usize]) -> Vec<usize> {
let mut res = Vec::new();
for i in 0..v.len() {
for j in i + 1..v.len() {
res.push(v[i] + v[j]);
}
}
res
}
fn assert_similar(real: Vec<usize>, test: Vec<usize>) {
let mut real = construct_input(&real);
let mut test = construct_input(&test);
real.sort();
test.sort();
assert_eq!(real, test);
}
fn assert_test(res: Vec<usize>) {
let input = construct_input(&res);
let n = res.len();
assert_similar(res, solve(input, n));
}
#[test]
fn test_sample() {
assert_test(vec![1, 3, 3, 3]);
}
#[test]
fn test_many() {
assert_test(vec![1, 2, 3, 4]);
assert_test(vec![1, 2, 3, 4, 5]);
assert_test(vec![1, 10, 11, 12]);
assert_test(vec![1, 11, 12, 13]);
assert_test(vec![1, 10, 20, 30]);
}
#[test]
fn test_medium() {
assert_test(vec![1, 2, 3, 4,1, 2, 3, 4, 5,100,5,19,312,523,456,34,56,12,4,2]);
}
#[test]
fn test_big() {
use rand::distributions::{Distribution, Uniform};
use std::time::{Duration, Instant};
const ITERS: u32 = 30;
const SIZE: usize = 100;
let mut time = Duration::from_nanos(1);
for i in 0..ITERS {
let mut model: Vec<usize> = vec![0; SIZE];
for i in 0..SIZE {
model[i] = Uniform::from(0..1_000_000).sample(&mut rand::thread_rng());
}
let input = construct_input(&model);
std::sync::atomic::fence(std::sync::atomic::Ordering::AcqRel);
let start = Instant::now();
std::sync::atomic::fence(std::sync::atomic::Ordering::AcqRel);
let output = solve(input, model.len());
std::sync::atomic::fence(std::sync::atomic::Ordering::AcqRel);
let stop = Instant::now();
std::sync::atomic::fence(std::sync::atomic::Ordering::AcqRel);
time += stop - start;
assert_similar(model, output);
}
let time = (time / ITERS).as_secs_f64();
assert!(time < 1.0, "Took time {}", time);
}
}

Test details

Test 1

Group: 1, 2, 3

Verdict: ACCEPTED

input
5
2 2 2 2 2 2 2 2 2 2

correct output
1 1 1 1 1 

user output
1 1 1 1 1

Test 2

Group: 1, 2, 3

Verdict: ACCEPTED

input
5
3 4 5 5 6 6 7 7 8 9

correct output
1 2 3 4 5 

user output
1 2 3 4 5

Test 3

Group: 1, 2, 3

Verdict: ACCEPTED

input
5
5 6 6 6 9 9 9 10 10 10

correct output
1 4 5 5 5 

user output
1 4 5 5 5

Test 4

Group: 1, 2, 3

Verdict: ACCEPTED

input
5
2 3 3 6 6 6 6 7 7 10

correct output
1 1 2 5 5 

user output
1 1 2 5 5

Test 5

Group: 1, 2, 3

Verdict: ACCEPTED

input
5
4 5 5 5 5 6 6 6 7 7

correct output
2 2 3 3 4 

user output
2 2 3 3 4

Test 6

Group: 2, 3

Verdict: ACCEPTED

input
20
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 ...

correct output
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ...

user output
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ...

Test 7

Group: 2, 3

Verdict: ACCEPTED

input
20
3 4 5 5 6 6 7 7 7 8 8 8 9 9 9 ...

correct output
1 2 3 4 5 6 7 8 9 10 11 12 13 ...

user output
1 2 3 4 5 6 7 8 9 10 11 12 13 ...

Test 8

Group: 2, 3

Verdict: ACCEPTED

input
20
52 55 55 57 62 62 63 64 66 71 ...

correct output
1 51 54 54 56 61 61 62 63 65 7...

user output
1 51 54 54 56 61 61 62 63 65 7...

Test 9

Group: 2, 3

Verdict: ACCEPTED

input
20
25 30 31 32 36 39 40 41 45 45 ...

correct output
8 17 22 23 24 28 43 50 53 55 6...

user output
8 17 22 23 24 28 43 50 53 55 6...

Test 10

Group: 2, 3

Verdict: ACCEPTED

input
20
9 10 14 17 17 20 21 22 24 25 2...

correct output
1 8 9 13 16 19 30 32 38 40 43 ...

user output
1 8 9 13 16 19 30 32 38 40 43 ...

Test 11

Group: 3

Verdict: ACCEPTED

input
100
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 ...

correct output
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ...

user output
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ...
Truncated

Test 12

Group: 3

Verdict: ACCEPTED

input
100
3 4 5 5 6 6 7 7 7 8 8 8 9 9 9 ...

correct output
1 2 3 4 5 6 7 8 9 10 11 12 13 ...

user output
1 2 3 4 5 6 7 8 9 10 11 12 13 ...
Truncated

Test 13

Group: 3

Verdict: ACCEPTED

input
100
502824619 505239810 505668108 ...

correct output
1 502824618 505239809 50566810...

user output
1 502824618 505239809 50566810...
Truncated

Test 14

Group: 3

Verdict: ACCEPTED

input
100
17871832 41618648 51611938 538...

correct output
3939271 13932561 37679377 4989...

user output
3939271 13932561 37679377 4989...
Truncated

Test 15

Group: 3

Verdict: ACCEPTED

input
100
70588435 115481965 116040218 1...

correct output
5902586 64685849 109579379 110...

user output
5902586 64685849 109579379 110...
Truncated