第5回 ドワンゴからの挑戦状 予選
第5回 ドワンゴからの挑戦状 予選に参加しました!
第5回 ドワンゴからの挑戦状 予選 旧版
第5回 ドワンゴからの挑戦状 予選 beta版
解けた問題だけ解説をしていきますー
要項
第5回 ドワンゴからの挑戦状 予選
rated 2800
11/24(土) 20:00 ~ 22:00 (120分)
200-400-600-800(500)-1000 (5問)
ペナルティ: 5分
方針
ABCdの3完1部分点を高速に、多分予選は通過できないけどパフォーマンスはかなり良くなるはず
A - Thumbnail
まず、平均点を求めます。
この時、平均点を求めると小数点以下の値で誤差を発生させる可能性があるため、あえて平均点の倍を求めます。
次に各についてと平均点の倍との差を求め、差が最小のものを選びます。
計算量はです。
#include<iostream> using namespace std; int main() { int N, a[100]; cin >> N; int sum = 0; // 平均点のN倍は総和に等しい for (int i = 0;i < N;++ i) { cin >> a[i]; sum += a[i]; a[i] *= N; // N倍することで誤差を消す! } int diff = abs(sum - a[0]), ans = 0; for (int i = 0;i < N;++ i) { if (diff > abs(sum - a[i])) { // もし、より差が小さいものを見つけたら更新 ans = i; diff = abs(sum - a[i]); } } cout << ans; return 0; }
B - Sum AND Subarrays
まず、連続した数列の和……は累積和なので予めを計算しておきましょう。
累積和が計算されているなら個の部分列を列挙するのもでできます。
次に、ビットごとの論理積を計算するという事は、少なくとも個の部分列で同一のビットが立っていないと立たせることができません。
逆に、そのようなビットでかつ最も高い位置にあるビットは立たせた方が良いです。
よって、一番上のビット()から順に個のビットが立つか貪欲に見ていき、立たせることができるならそれを立たせると良いです。
その時、ついでにそのビットが立たないもの全てを0埋めしておくとバグを防ぐこともできます。
計算量はです。
C - k-DMC
制約よりがかなり小さいので、を考えます。
各クエリについて独立っぽいので、1回のクエリについてはで解く必要があるようです。
まず、カウンターとしてを定義します。
そして左から順にみていき、'D'が出てきたらを1増やします。
次に、'M'が出てきたら、今まで'D'が出てきた個数分だけを増やします。すなわちですね。
次に、'C'が出てきたらをだけ増やします。
これは、というのは'D'と'C'に囲まれた'M'の個数(複数の'D'と共有して挟まれたならその個数だけ掛けたもの)を指すので、これがそのまま答えに足すべき個数だからです。
また、の制約があるので、最後に個前に'D'が出てきたなら個前から今の地点までの'M'の個数分だけを減らします。
これは、予め'M'について出現個数を累積和で求めておけばで求めることができますね。
以上の操作により、左から順に全ての操作をで求められたので、各クエリについて、よって計算量はとなりました。
結果
ooox- 3完(1200点) 17:36(3WA)-49:57(4WA)-89:08(1WA) / 129:08
289位 パフォーマンス: 1819
レート: 1642→ 1661(+19)
感想
ちょっと64bit整数関連でバグらせたけど、まぁ妥当な感じではないでしょうか。
C問題は問題としては面白く、時間もかかる問題だったので発想ができて解けたのは良かった範囲だと思います。
ただもう少し早解きしたかったなぁ……。