AtCoder Grand Contest 049
コンテスト前のレート:1670
レート通りのパフォーマンスが得られる順位:496位(600点、41分56秒)
A - Erasing Vertices
問題
40分くらいかけて解けず。
最終的に実装が重そうな解法を考えてはいたが、そこまで自信があったわけでもなく、実装に時間かけて失敗するくらいならとC問題に賭けていた。
B - Flip Digits
問題
40分ほどで一応通せた。
初回提出がWAで死んだかと思ったけどなんとか。
思考過程
- 例3などを元に動きを考えてみると、"01"→"10"のように変えて'1'を左に動かしていくのが基本で、'1'を右に動かしていくことはできない。
- '1'の数が増えることはなく、"01"→"10"で変わらないか、"11"→"00"で個減るかしかない。
- とりあえず右から見ていって、に現れる'1'の累積数を比較し、となる箇所があったら、'1'を右に動かす必要が出てくるので不可能。
- 最終的に'1'の個数の差が奇数の場合も、'1'が減るのは個ずつなので不可能。
- もう一度右から調べていき、に現れる'1'を対応付けていって、その位置の差を答えに足していく。
- 余った個は、一番左まで持っていくと、"11"→"00"にできるので、その操作に必要な回数を答えに足す。 →半分くらいWA
- 別に一番左まで持っていかなくても"11"→"00"の操作を行うことはでき、を崩さない範囲でなるべく右の方でやった方が良さそう。
- の各'1'をのどれかの'1'と対応付けた上、の残った'1'を寄せて"11"→"00"を行うことになる。
- 対応付けについては、で'1'となっている位置をあらかじめTreeSetに入れておき、を左から調べて各'1'の位置以上で最小の値をTreeSetから取得していく。取得したものを取り除くことで、の同じ位置と複数対応することを避ける。
- TreeSetに個の要素が残るので、それらは小さい順に個ずつくっつける。
- つ目の位置を、つ目の位置をとすると、をの隣に持ってくるのに回、"11"→"00"の操作に回かかるので、足して回。
import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.TreeSet; public class Main { public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int n = Integer.parseInt(br.readLine()); char[] s = br.readLine().toCharArray(); char[] t = br.readLine().toCharArray(); br.close(); int c1 = 0; int c2 = 0; TreeSet<Integer> set = new TreeSet<>(); for (int i = n - 1; i >= 0; i--) { if (s[i] == '1') { c1++; set.add(i); // 思考過程9の事前処理 } if (t[i] == '1') { c2++; } // 思考過程3 if (c1 < c2) { System.out.println(-1); return; } } // 思考過程4 int d = c1 - c2; if (d % 2 == 1) { System.out.println(-1); return; } long ans = 0; // 思考過程9 for (int i = 0; i < n; i++) { if (t[i] == '1') { Integer x = set.ceiling(i); set.remove(x); ans += x - i; } } // 思考過程10, 11 while (!set.isEmpty()) { int x = set.pollFirst(); int y = set.pollFirst(); ans += y - x; } System.out.println(ans); } }
ここまで79分54秒+1ペナ。485位。
C - Robots
問題
2時間近く費やして解けず。
初手で、適当な大きい数に変えれば実質ボールをなくすことができると思ってしまい、増やせるケースに全然気付かず、結局問題を正しく把握することすらできていなかった。
思考過程
- 例2を元に左からDPしていくことを考える。
- 番目まで見たとき、をに減らすしかないので。
※実はをに減らしてに書き換えれば回で済むが、コンテスト終了まで気付くことはなかった。以下はそれが完全に抜けていることが前提。
- 番目は番目まで届かず全く関係ないので。
- 番目はちょうど前のつを破壊し、座標で止まるので。
・・・ - 色々なパターンを考えた結果、整理すると、が来たら、。
- の場合は、からまでの範囲の左から途中までは壊さず、途中から右は壊すという操作ができるため、となる最小のを求め、~の最小値。
- これはセグ木に乗せるだけ。 →8/41しか通らない。
- ボールの値を適当な大きい数に変えて捨てることしか考えていなかったが、普通にロボットの動きに影響ある範囲の数に書き換え、後ろの方のロボットがより前の方まで壊せるようにすることもできる。
※なお、この時点ではまだを減らしてに足すことしか考えていない。 - これだとはかかりそうな・・・という思考から抜け出すことなく終了。
最終結果:Bの1完、84分54秒、610位、パフォーマンス1437
レート変動:1670→1648(-22)
3時間20分もあっても、後半座ってるだけだろうと思っていたが、結局ほぼ休むこともなく時間いっぱい取り組んでいたと思う。
しかし、後から見ればAを捨ててCに粘着したのが賭けにすらなっておらず、誤読で半分の時間を浪費していただけなのが悲しいところ。
AGCに得意意識を持っていたのは一体いつのことだったか。
(始めたての頃の方が、Aの早解きを成功させたり、Bの水~青diffを通したりして稼いでいた。)