公式
C - Sushi 解説
by
C - Sushi 解説
by
cn449
ネタはより軽いものに交換しても損しないため、軽いものから順に使っていくことにして構いません。
寿司に使うネタの重さを \(b_1 \leq b_2 \leq \ldots \leq b_t\) とし、重さ \(b_i\) のネタと組み合わせるシャリの重さを \(a_i\) としたとき、\(a_1 \leq a_2 \leq \ldots \leq a_t\) としてよいです。これは、\(a_i > a_{i + 1}\) であるとき \(2a_i \geq b_i\) かつ \(2a_{i + 1} \geq b_{i + 1}\) ならば \(2a_{i+1} \geq b_i\) かつ \(2a_i \geq b_{i+1}\) であることから、\(a_i > a_{i + 1}\) なる \(i\) が存在する限り \(a_i\) と \(a_{i + 1}\) を swap する操作を行い続けてよいことから従います。
従って、ネタを軽い方から順に見ていき、組み合わせることのできるシャリが存在するならば実際に組み合わせる貪欲法が正当です。
これは \(A, B\) をソートして尺取り法の要領で実装することができます。ソートがボトルネックとなり、時間計算量は \(O(N \log N + M \log M)\) です。
実装例
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<int> a(n), b(m);
for (int i = 0; i < n; i++) cin >> a[i];
for (int i = 0; i < m; i++) cin >> b[i];
sort(a.begin(), a.end());
sort(b.begin(), b.end());
int x = 0, ans = 0;
for (int i = 0; i < m; i++) {
while (x < n && a[x] * 2 < b[i]) x++;
if (x < n) {
x++;
ans++;
}
}
cout << ans << '\n';
}
投稿日時:
最終更新: