AtCoder Grand Contest 29の参加記録。
A
xoxooox のようにオセロの並びが与えられるので, 隣合うox を xo にする操作が最大何回行えるか求める.
oooox の場合, xooooとなるまでに4回操作できる.
ooooxx の場合, まず右から二つ目のxを↑の様に動かしてからxoooo + xとみるとそれぞれのxに対する操作は独立.
なので各xの左側にあるoの数の和を求めればいい.
解答
fn main() {
let mut ans = 0;
let s = read_one::<String>().chars().collect::<Vec<char>>();
let mut cnt = 0;
for i in 0..s.len() {
if s[i] == 'B' { cnt += 1; }
if s[i] == 'W' { ans += cnt; }
}
println!("{}", ans);
}
上の解答はWAになります()
Rustの数値リテラルにおける型推論のデフォルトはi32のため, s.len() < O(10^5)の制約ではオーバーフローしうる.
5分で解答してWA食らって正直全く分からなかった.これに気付くまで25分.
流石に初歩過ぎるので反省.
B
3 11 14 5 13 のように数列が与えられる. この中から和が2^kの形になるようにペアをつくるとき, 最大いくつ作れるか.
↑の例だと, ペアは(3, 5), (3, 13), (5, 11) の3通り考えられる. 複数回使うことは出来ないので, 2部グラフの最大マッチングか? n <= 2 * 10^5からできる候補なら計算量O(NM)でも間に合うのか? などと考えていた(無事TLE).
まずソートして, 各a_iに対しそれより大きい最小の2^kを求める.
2^k - a_iが数列の中に存在するかどうかbinary search等で求めてペアの候補とする.
ペアの候補は, 大きいものから順に選択していけば最大となる.
解答
fn main() {
let n = read_one::<usize>();
let mut an = read::<usize>();
an.sort();
let mut graph = Vec::new();
let mut bn = an.clone();
for i in 0..n {
let x = bn.binary_search(&an[i]).unwrap();
// 自身がペア対象にならないように一旦
bn.remove(x);
let mut ceil = 2;
while ceil <= an[i] {
ceil *= 2;
}
match bn.binary_search(&(ceil - an[i])) {
Ok(n) => { graph.push((i, n)); },
_ => {}
}
// 自身を戻す
bn.insert(x, an[i]);
}
/* 最大マッチングWA
let n = graph.len();
let mut dinitz = Dinitz::new(n * 2 + 2);
for (a, b) in graph {
dinitz.add_edge(a, b, 1);
dinitz.add_edge(b, a, 1);
}
println!("{:?}", dinitz.max_flow(n * 2, n * 2 + 1));
*/
}
所感
Aのミスで800位くらい落ちてて草も生えない.
Bは2部マッチングを勉強したあとだったのでそれに引っ張られた.
精進の量がたりてないので300~500埋めをやろう.
Comments