ABC 312
Table of Contents
A. Chord
https://atcoder.jp/contests/abc312/tasks/abc312_a
B. TaK Code
https://atcoder.jp/contests/abc312/tasks/abc312_b
C. Invisible Hand
https://atcoder.jp/contests/abc312/tasks/abc312_c
D. Count Bracket Sequences
https://atcoder.jp/contests/abc312/tasks/abc312_d
解説 AC
E. Tangency of Cuboids
https://atcoder.jp/contests/abc312/tasks/abc312_e
F. Cans and Openers
https://atcoder.jp/contests/abc312/tasks/abc312_f
2026/2/24 自力 AC
缶は満足度の高い順、缶切りは使用できる個数が大きい順に使うのが最適。
缶切りが必要な缶の個数を決めると必要な缶切りの個数も決まる。 個数に余裕がある場合は缶切り不要な缶も使うとすれば良い。 必要な缶切りの個数は累積和を取っておけば二分探索で求められるので計算量は $O(N \log N)$ になる。
void solve() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
ll N, M;
cin >> N >> M;
vll need, needless, opener;
rep(i, N) {
ll t, x;
cin >> t >> x;
if (t == 0) needless.pb(x);
if (t == 1) need.pb(x);
if (t == 2) opener.pb(x);
}
sort(rall(needless));
sort(rall(need));
sort(rall(opener));
rep(i, (ll)opener.size() - 1) {
opener[i + 1] += opener[i];
}
rep(i, (ll)needless.size() - 1) {
needless[i + 1] += needless[i];
}
rep(i, (ll)need.size() - 1) {
need[i + 1] += need[i];
}
ll ans = 0;
if (needless.size()) {
ans = needless[min(M - 1, (ll)needless.size() - 1)];
}
rep(i, (ll)need.size()) {
ll ncan = i + 1;
if (!opener.size()) break;
auto it = lower_bound(all(opener), ncan);
if (it == opener.end()) break;
// i+1 個の「缶切りが必要な缶」を開けるために必要な缶切りの個数
ll need_opener = it - opener.begin() + 1;
if (need_opener + ncan > M) continue;
ll sum = need[i];
ll m = M - need_opener - ncan;
if (m > 0) { // 缶切り不要な缶が選べる場合、選べるだけ使う
int id = min(m - 1, (ll)needless.size() - 1);
sum += needless[id];
}
chmax(ans, sum);
}
cout << ans << endl;
}
G. Avoid Straight Line
https://atcoder.jp/contests/abc312/tasks/abc312_g