結果
問題 |
No.5021 Addition Pyramid
|
ユーザー |
![]() |
提出日時 | 2025-02-25 22:58:30 |
言語 | Rust (1.83.0 + proconio) |
結果 |
AC
|
実行時間 | 1,902 ms / 2,000 ms |
コード長 | 8,936 bytes |
コンパイル時間 | 12,915 ms |
コンパイル使用メモリ | 401,636 KB |
実行使用メモリ | 6,820 KB |
スコア | 13,463,905 |
最終ジャッジ日時 | 2025-02-25 23:00:23 |
合計ジャッジ時間 | 112,224 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
純コード判定しない問題か言語 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 50 |
コンパイルメッセージ
warning: unexpected `cfg` condition value: `local` --> src/main.rs:196:15 | 196 | #[cfg(feature = "local")] | ^^^^^^^^^^^^^^^^^ help: remove the condition | = note: no expected values for `feature` = help: consider adding `local` as a feature in `Cargo.toml` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `local` --> src/main.rs:200:19 | 200 | #[cfg(not(feature = "local"))] | ^^^^^^^^^^^^^^^^^ help: remove the condition | = note: no expected values for `feature` = help: consider adding `local` as a feature in `Cargo.toml` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration warning: value assigned to `newidx` is never read --> src/main.rs:42:17 | 42 | let mut newidx = 0; | ^^^^^^ | = help: maybe it is overwritten before being read? = note: `#[warn(unused_assignments)]` on by default
ソースコード
#![allow(non_snake_case)] #![allow(dead_code)] #![allow(unused_imports)] #![allow(unused_variables)] #![allow(unused_mut)] #![allow(non_upper_case_globals)] // use itertools::*; use proconio::input; use proconio::marker::*; use proconio::*; // use rand::prelude::*; // use rand_pcg::*; use std::collections::*; use std::collections::{HashSet, VecDeque}; use std::ops::*; const MOD: usize = 100000000; const NUM: usize = 25 * 51; const TIME_LIMIT: f64 = 1.9; fn main() { let inp = get_input(); let mut rnd = XorShift::new(20250225); let mut state = State::new(&inp); // state.change(&inp, inp.n - 3, 10); solve2(&mut state, &inp, &mut rnd); state.print(&inp); state.calc_score(&inp); // eprintln!("{:?}", state.now.data.clone()); } fn solve(state: &mut State, inp: &Input, rnd: &mut XorShift) { for i in 0..inp.n { // let idx = to_index(inp.n - 1, i); state.change(inp, i, inp.AA[inp.n - 1][i]) } } fn solve2(state: &mut State, inp: &Input, rnd: &mut XorShift) { let mut best = state.clone(); while TIME_LIMIT > get_time() { let newval = rnd.gen_range(0, 100000000); let mut newidx = 0; if rnd.next() % 2 == 0 { newidx = rnd.gen_range(0, inp.n); } else { let hoge = state.now.query(0, NUM).0; let left = to_ij(hoge).0; let right = (left + rnd.gen_range(1, 5)).min(inp.n); // eprintln!("left right {} {}", left, right); newidx = rnd.gen_range(left, right); } // eprintln!("newval {} newidx {}", newval, newidx); let idx = to_index(inp.n - 1, newidx); // eprintln!("idx {}", idx); let preval = state.now.get(idx).1; let prescore = state.score; state.change(inp, newidx, newval); let nexscore = state.score; if prescore > nexscore { state.change(inp, newidx, preval); } } } struct XorShift { state: usize, } impl XorShift { fn new(seed: usize) -> Self { let state = if seed != 0 { seed } else { 2463534242 }; // 0回避 Self { state } } fn next(&mut self) -> usize { let mut x = self.state; x ^= x << 13; x ^= x >> 17; x ^= x << 5; self.state = x; x } fn gen_range(&mut self, left: usize, right: usize) -> usize { self.next() % (right - left) + left } } pub struct Input { n: usize, AA: Vec<Vec<usize>>, } #[derive(Clone)] pub struct State { bottom: Vec<usize>, now: SegmentTree, score: usize, } impl State { fn new(inp: &Input) -> Self { let mut bottom = vec![0; inp.n]; let num = inp.n * inp.n / 2 + 50; let mut values = vec![]; for idx in 0..NUM { let (i, j) = to_ij(idx); // eprintln!("ij {} {}", i, j); values.push((idx, 0, inp.AA[i][j])); } let mut now = SegmentTree::build(values); let mut score = 0; score += calc_edge(now.query(0, NUM)); eprintln!("initial {}", 50000000 - score); Self { bottom, now, score } } fn calc_score(&self, inp: &Input) { let mx = calc_edge(self.now.query(0, NUM)); eprintln!("Score {}", 50000000 - mx); // assert_eq!(mx, self.score); } fn recalc_score(&mut self, inp: &Input) { let mx = calc_edge(self.now.query(0, NUM)); self.score = 50000000 - mx; // eprintln!("Score {}", mx); // assert_eq!(mx, self.score); } fn change(&mut self, inp: &Input, idx: usize, delta: usize) { let mut haba = 1; let index = to_index(inp.n - 1, idx); // let mut newval = self.now.get(index).1; // newval += delta; let newval = delta; self.now.data[self.now.size + index] = (self.now.get(index).0, newval, self.now.get(index).2); for i in (0..inp.n - 1).rev() { for j in idx - haba..=idx.min(i) { let idx = to_index(i, j); let idx1 = to_index(i + 1, j); let idx2 = to_index(i + 1, j + 1); let mut newval = self.now.get(idx1).1 + self.now.get(idx2).1; if newval >= MOD { newval -= MOD; } self.now.update(idx, newval); // eprintln!("i j {} {}", i, j); } if idx - haba > 0 { haba += 1; } } self.recalc_score(inp); } fn print(&self, inp: &Input) { for i in 0..inp.n { let idx = to_index(inp.n - 1, i); if i == inp.n - 1 { println!("{}", self.now.get(idx).1) } else { print!("{} ", self.now.get(idx).1); } } } // fn get_worst_idx(&self) -> (usize, usize) { // self.now.query(0, NUM) // } // fn get_candidate_idx(&self) -> usize {} // fn gather_vals(&self, idx:usize){ // for i in・ // } } fn get_input() -> Input { input! {n:usize}; let mut AA = vec![]; for i in 0..n { input! {temp:[usize;i+1]}; AA.push(temp); } Input { n, AA } } pub fn get_time() -> f64 { static mut STIME: f64 = -1.0; // 初期値 let t = std::time::SystemTime::now() // nowを取得 .duration_since(std::time::UNIX_EPOCH) .unwrap(); // a.duration_since(b)だとa>bが前提 let ms = t.as_secs() as f64 + t.subsec_nanos() as f64 * 1e-9; // as_secsが秒, .subsec_nanos()が小数点以下の秒 unsafe { if STIME < 0.0 { STIME = ms; // 経過時間の初期化 } // ローカル環境とジャッジ環境の実行速度差はget_timeで吸収しておくと便利 #[cfg(feature = "local")] { (ms - STIME) * 1.3 } #[cfg(not(feature = "local"))] { ms - STIME } } } #[derive(Clone)] struct SegmentTree { size: usize, data: Vec<(usize, usize, usize)>, // (index, value,AA) } impl SegmentTree { /// 新規作成 (空のセグメントツリー) fn new(n: usize) -> Self { let size = n.next_power_of_two(); Self { size, data: vec![(0, 0, 0); 2 * size], } } /// (index, value) の Vec から SegmentTree を構築 fn build(values: Vec<(usize, usize, usize)>) -> Self { let n = values.len(); let size = n.next_power_of_two(); let mut seg_tree = Self { size, data: vec![(0, 0, 0); 2 * size], }; // リーフノードにデータをセット for (i, &(index, value, aa)) in values.iter().enumerate() { seg_tree.data[i + size] = (index, value, aa); } // 下から上へマージして構築 for i in (1..size).rev() { seg_tree.data[i] = seg_tree.merge(seg_tree.data[2 * i], seg_tree.data[2 * i + 1]); } seg_tree } /// 値を更新 (pos 番目の要素を value にする) fn update(&mut self, mut pos: usize, value: usize) { pos += self.size; let pre = self.data[pos].2; self.data[pos] = (pos - self.size, value, pre); while pos > 1 { pos /= 2; self.data[pos] = self.merge(self.data[2 * pos], self.data[2 * pos + 1]); } } fn get(&self, idx: usize) -> (usize, usize, usize) { self.data[idx + self.size] } /// 区間 [l, r) の最大値 (index, value) を取得 fn query(&self, mut l: usize, mut r: usize) -> (usize, usize, usize) { l += self.size; r += self.size; let mut res_left = (0, 0, 0); let mut res_right = (0, 0, 0); while l < r { if l % 2 == 1 { res_left = self.merge(res_left, self.data[l]); l += 1; } if r % 2 == 1 { r -= 1; res_right = self.merge(self.data[r], res_right); } l /= 2; r /= 2; } self.merge(res_left, res_right) } /// 2 つのノードをマージする (valueが大きい方を選択) fn merge(&self, a: (usize, usize, usize), b: (usize, usize, usize)) -> (usize, usize, usize) { let v1 = calc_edge(a); let v2 = calc_edge(b); if v1 >= v2 { a } else { b } } } /// (i, j) -> idx 変換 (O(1)) fn to_index(i: usize, j: usize) -> usize { (i * (i + 1)) / 2 + j } /// idx -> (i, j) 変換 (O(1)) fn to_ij(idx: usize) -> (usize, usize) { // i を求める let i = ((-1.0 + (1.0 + 8.0 * idx as f64).sqrt()) / 2.0).floor() as usize; let j = idx - (i * (i + 1)) / 2; (i, j) } fn calc_edge(hoge: (usize, usize, usize)) -> usize { let v1 = hoge.1.abs_diff(hoge.2); let v2 = MOD.abs_diff(v1); v1.min(v2) }