E - Simultaneous Kagamimochi Editorial
by
MMNMM
\(K\) 個 \((0\leq K\leq\dfrac N2)\) の鏡餅を作るとき、先頭 \(K\) 個と末尾 \(K\) 個の餅を使うとしてかまいません(上に乗せられている餅が先頭 \(K\) 個と異なる場合、先頭 \(K\) 個の餅が上になるように入れ替えることができます。末尾 \(K\) 個も同様です)。
また、上に乗せる \(K\) 個の餅と下段として使われる \(K\) 個の餅を決めたとき、それらをすべて使って \(K\) 個の鏡餅が作れることは、それぞれ小さいほうから組にしたときに \(K\) 個の鏡餅が作れることと同値です(\(\Leftarrow\) は明らかです。\(\Rightarrow\) は、出来上がった鏡餅を上の餅の大きさでソートしたときに下の餅がソートされていないなら、下の餅をソートしても \(K\) 個の鏡餅を作れることから言えます)。
以上より、\(K\) を定めたときに \(K\) 個の鏡餅が作れるかを判定することは \(O(K)\) 時間で可能です。
ある非負整数 \(k\) について鏡餅を \(k\) 個作れるなら、任意の非負整数 \(l\ (l\leq k)\) について鏡餅を \(l\) 個作れるので、二分探索を行うことでこの問題を解くことができます。
時間計算量は \(O(N\log N)\) となります。
#include <algorithm>
#include <iostream>
#include <vector>
#include <ranges>
int main() {
using namespace std;
unsigned N;
cin >> N;
vector<unsigned> A(N);
for (auto&& a : A)
cin >> a;
// 判定関数
// K 個の鏡餅を作ることができるか?
const auto check{
[N, &A](unsigned K) {
for (unsigned i = 0; i < K; ++i)
// 先頭と末尾から K 個ずつ取ってきて
if (A[i] * 2 > A[N - K + i])
// どれか 1 つでも半分より大きかったら false
return false;
// そうでなければ true
return true;
}
};
// 0 から N / 2 の間で、判定関数が true になる最大の値(false になる最小の値 - 1)を二分探索で求める
cout << *ranges::partition_point(views::iota(0U, N / 2 + 1), check) - 1 << endl;
return 0;
}
posted:
last update: