ABC141 バチャ メモ
atcoder.jp
Fめっちゃムズいじゃん
A
バグらないように書くB
まあstringでfindすると楽に書けそうC
Qを全要素引いておいて、正解したら1ptあげれば答えが出るD
消したら一番お得なのは明らかに一番大きい要素priority_queueに入れてQ回回します
E
LCSのDPに対して のとき、 までの長さにしかならないという制約を課すと解けるdpを観察すると実はlenを決め打ちしてn回程度dpをしているのと変わらない。
は固定であるため、dpは壊れてない(よくわからない説明だけど)。
各接頭辞に対してz_algorithmを用いても解ける。
F
Fは大事なので大きく見出しをつけます赤の全xorを , 青の全xorを とすると、
となる(ここではand を としている)。
, すなわち全ての要素の xor を取った値 について考える。
ここから桁 について述べる時、 の添え字をつける。
の時は、 を無条件に答えに足すことが出来る。
なぜなら のとき、 であり、 のとき、 であるため、この桁の和は必ず になるからである。
の時は、 に調整できれば、 に出来る。
そのため、 を最大化する問題となる。
まず、左側の桁から できるか判断して にしていくと、最適であることがわかる。
ただ、 を作れるかどうかがすぐにはわからない。
ここで、配列に対して掃き出し法を利用する。
そうすると、各桁について 要素だけに出来る部分が出来る。これを自由度のある桁と呼ぶことにする。
左側から自由度のある桁について、 を入れていけば、 の最大化すなわち の最大化が出来、 これを 倍した値を の時の解に足してあげればこの問題は解くことが出来る。
F のソース
void gaussJordan(vll &A, ll size) { int s = 0; for (ll b = size-1; b >= 0; b--) { //探す ll pos = -1; for (int i = s; i < A.size(); i++) { if ((A[i]>>b) & 1) { pos = i; break; } } if (pos == -1) continue; if (pos != s) swap(A[pos], A[s]); //消す for (int i = 0; i < A.size(); i++) { if (i != s && ((A[i]>>b) & 1)) A[i] ^= A[s]; } s++; } } void Main() { ll N; cin >> N; vll A(N); cin >> A; ll xd = 0; ll size = 60; ll ans = 0; for (auto &v : A) xd ^= v; for (int i = 0; i < size; i++) { if ((xd>>i) & 1) { ans += (1ll<<i); for (auto &v : A) v &= (~(1ll<<i)); } } gaussJordan(A, size); ll xd2 = 0; for (auto &v : A) xd2 ^= v; cout << ans + xd2 * 2 << endl; }
感想
なんかEまでは早解きができたなFみたいなのは、すごい典型感があるので、ちゃんと抑えたい
特に掃き出しするところとか、やっとかんと、やばいだろ