結果
| 問題 | No.3244 Range Multiple of 8 Query |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-01-06 23:09:14 |
| 言語 | Rust (1.92.0 + proconio + num) |
| 結果 |
AC
|
| 実行時間 | 899 ms / 5,000 ms |
| コード長 | 4,192 bytes |
| 記録 | |
| コンパイル時間 | 26,252 ms |
| コンパイル使用メモリ | 411,452 KB |
| 実行使用メモリ | 20,432 KB |
| 最終ジャッジ日時 | 2026-01-06 23:10:00 |
| 合計ジャッジ時間 | 44,312 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 40 |
ソースコード
use proconio::input;
fn get_last_three_values_digits() -> Vec<[u8; 3]> {
let mut v = Vec::new();
// Pythonでは i in range(1000), if i%8==0 で i0=1000+i の下3桁を見ている
// 下3桁は 000..999(先頭0含む)になりうるので %1000 で取り、各桁0を弾く
for i in (0..1000).step_by(8) {
let i0 = 1000 + i;
let x = i0 % 1000; // 下3桁
let a = (x / 100) as u8;
let b = ((x / 10) % 10) as u8;
let c = (x % 10) as u8;
if a != 0 && b != 0 && c != 0 {
v.push([a, b, c]);
}
}
v
}
fn solve_length1(ch: u8) -> i64 {
if ch == b'8' { 0 } else { -1 }
}
fn solve_length2(s: &[u8]) -> i64 {
// ひっくり返さない場合
let a = (s[0] - b'0') as i32;
let b = (s[1] - b'0') as i32;
let x = a * 10 + b;
if x % 8 == 0 {
return 0;
}
// ひっくり返す場合
let y = b * 10 + a;
if y % 8 == 0 { 1 } else { -1 }
}
fn solve_length3(
prev_pos: &Vec<Vec<i32>>,
last_three_values: &Vec<[u8; 3]>,
l: usize,
r: usize,
) -> i64 {
let mut best: i64 = i64::MAX;
for digits in last_three_values.iter() {
let mut ans: i64 = 0;
let mut target_index: isize = r as isize;
let mut used: Vec<usize> = Vec::with_capacity(3);
let mut ok = true;
// Python: for ideal_digit in reversed(ideal_value)
// digits = [a,b,c] なので reversed は c,b,a
for &d in [digits[2], digits[1], digits[0]].iter() {
if target_index < 0 {
ok = false;
break;
}
let mut ind: i32 = prev_pos[d as usize][target_index as usize];
// while l < ind and ind in used_index:
while ind != -1 && (l as i32) < ind && used.contains(&(ind as usize)) {
let pi = ind as usize;
if pi == 0 {
ind = -1;
break;
}
ind = prev_pos[d as usize][pi - 1];
}
if ind < l as i32 || ind == -1 || used.contains(&(ind as usize)) {
ok = false;
break;
}
let ind_u = ind as usize;
let t_u = target_index as usize;
// w = count(used_index i where ind <= i <= target_index)
let w = used.iter().filter(|&&i| ind_u <= i && i <= t_u).count() as i64;
// ans += target_index - ind - w
ans += (t_u as i64) - (ind_u as i64) - w;
used.push(ind_u);
// while target_index in used_index: target_index -= 1
while target_index >= 0 && used.contains(&(target_index as usize)) {
target_index -= 1;
// target_index が l を下回っても、次の digit の探索で自然に失敗するのでそのまま
}
}
if ok {
if ans < best {
best = ans;
}
}
}
if best == i64::MAX { -1 } else { best }
}
fn main() {
input! {
n: usize,
q: usize,
s: String,
lr: [(usize, usize); q],
}
let bytes = s.as_bytes();
// 3桁以上の場合、下3桁が以下のようになっていればOK(Pythonの get_last_three_values 相当)
let last_three_values = get_last_three_values_digits();
// seg_tree_list 相当: prev_pos[d][i] = i 以下で数字 d が最後に出た位置(なければ -1)
let mut prev_pos: Vec<Vec<i32>> = vec![vec![-1; n]; 10];
for d in 0..10 {
let mut last_i: i32 = -1;
for i in 0..n {
if bytes[i] == b'0' + (d as u8) {
last_i = i as i32;
}
prev_pos[d][i] = last_i;
}
}
let mut out = String::new();
for (l1, r1) in lr {
let l = l1 - 1;
let r = r1 - 1;
let res = if r == l {
solve_length1(bytes[l])
} else if r == l + 1 {
solve_length2(&bytes[l..=r])
} else {
solve_length3(&prev_pos, &last_three_values, l, r)
};
out.push_str(&format!("{}\n", res));
}
print!("{}", out);
}