結果
| 問題 | No.5020 Averaging |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-05-28 22:24:39 |
| 言語 | Rust (1.94.0 + proconio + num + itertools) |
| 結果 |
AC
|
| 実行時間 | 2 ms / 1,000 ms |
| コード長 | 4,297 bytes |
| 記録 | |
| コンパイル時間 | 1,695 ms |
| コンパイル使用メモリ | 208,288 KB |
| 実行使用メモリ | 6,400 KB |
| スコア | 17,156,809 |
| 最終ジャッジ日時 | 2026-05-28 22:24:46 |
| 合計ジャッジ時間 | 4,380 ms |
|
ジャッジサーバーID (参考情報) |
judge1_0 / judge2_1 |
| 純コード判定しない問題か言語 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 50 |
コンパイルメッセージ
warning: constant `OPERATION_LIMIT` is never used
--> src/main.rs:6:7
|
6 | const OPERATION_LIMIT: usize = 50;
| ^^^^^^^^^^^^^^^
|
= note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default
warning: function `solver1` is never used
--> src/main.rs:33:4
|
33 | fn solver1(n: usize, mut ab: Vec<(i64, i64)>) -> Vec<(usize, usize)> {
| ^^^^^^^
ソースコード
use proconio::input;
use std::collections::HashSet;
//const LOCAL_EXECUTE:bool = true;
const TARGET: i64 = 500_000_000_000_000_000;
const OPERATION_LIMIT: usize = 50;
fn operatioin(u: usize, v: usize, ab: &mut [(i64, i64)]) {
let (a1, b1) = ab[u];
let (a2, b2) = ab[v];
let am = (a1 + a2) / 2;
let bm = (b1 + b2) / 2;
ab[u] = (am, bm);
ab[v] = (am, bm);
}
fn calc_score(mut ab: Vec<(i64, i64)>, op: &[(usize, usize)]) -> i64 {
for &(u, v) in op {
operatioin(u, v, &mut ab);
}
let (a, b) = ab[0];
let v1 = a.abs_diff(TARGET);
let v2 = b.abs_diff(TARGET);
let m = v1.max(v2);
let x = op.len() as i64;
if m == 0 {
return 2000050 - x;
}
let score = 2000000.0 - 100000.0 * f64::log10(m as f64 + 1.0);
score as i64
}
fn solver1(n: usize, mut ab: Vec<(i64, i64)>) -> Vec<(usize, usize)> {
// いったん全部の平均に近づくようにやってみる
// a_max - a_min と b_max - b_min の一番大きな組み合わせのカードで平均を取る
let mut ans = vec![];
for _ in 0..OPERATION_LIMIT {
// let mut dist_max = -1;
// let mut i = 0;
// let mut j = 0;
// for ii in 0..(n - 1) {
// let (ai, bi) = ab[ii];
// for jj in (ii + 1)..n {
// let (aj, bj) = ab[jj];
// let dist = (ai - aj).abs().max((bi - bj).abs());
// if dist > dist_max {
// dist_max = dist;
// i = ii;
// j = jj
// }
// }
// }
let (i, j) = (0..n - 1)
.into_iter()
.map(|i| {
let (dist, j) = (i + 1..n)
.into_iter()
.map(|j| {
let (ai, bi) = ab[i];
let (aj, bj) = ab[j];
let dist = ai.abs_diff(aj).max(bi.abs_diff(bj));
(dist, j)
})
.max()
.unwrap();
(dist, (i, j))
})
.max()
.unwrap()
.1;
ans.push((i, j));
operatioin(i, j, &mut ab);
}
ans
}
fn find_best(ab: &[(i64, i64)], ignore_idx: &mut HashSet<usize>) {
let (mut a_sum, mut b_sum) = (0, 0);
for &(a, b) in ab {
a_sum -= TARGET;
a_sum += a;
b_sum -= TARGET;
b_sum += b;
}
let mut best_dist = i64::MAX;
let mut best_idx = 1;
for (i, &(a, b)) in ab.iter().enumerate() {
if i == 0 {
continue;
}
if ignore_idx.contains(&i) {
continue;
}
let dist = (a_sum - a + TARGET).abs() + (b_sum - b + TARGET).abs();
if dist < best_dist {
best_dist = dist;
best_idx = i;
}
}
ignore_idx.insert(best_idx);
}
fn solver2(n: usize, mut ab: Vec<(i64, i64)>) -> Vec<(usize, usize)> {
// 仲間外れを1枚決めて、それ以外で solver1 の要領で中心に寄る
// 2段階に分けて2回それを行う
let mut ans = vec![];
let mut ignore_idx = HashSet::new();
for loops in 0..50 {
if loops % 4 == 0 {
find_best(&ab, &mut ignore_idx);
}
let mut dist_max = -1;
let mut i = 0;
let mut j = 0;
for ii in 0..(n - 1) {
if ignore_idx.contains(&ii) {
continue;
}
let (ai, bi) = ab[ii];
for jj in (ii + 1)..n {
if ignore_idx.contains(&jj) {
continue;
}
let (aj, bj) = ab[jj];
let dist = (ai - aj).abs().max((bi - bj).abs());
if dist > dist_max {
dist_max = dist;
i = ii;
j = jj
}
}
}
ans.push((i, j));
operatioin(i, j, &mut ab);
}
ans
}
fn main() {
input! {
n:usize,
ab:[(i64, i64); n]
}
// solve
let ans = solver2(n, ab.clone());
eprintln!("{}", calc_score(ab.clone(), &ans));
println!("{}", ans.len());
for &(u, v) in &ans {
println!("{} {}", u + 1, v + 1);
}
}