Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
A chosen set of size is valid exactly when every chosen particle has . So after fixing , the constraint becomes a simple filter, not a weird subset DP.
Ignore shop particles first. For a fixed , only particles with can be used, and among them you want the largest energies.
Sweep from down to . As decreases, more particles become eligible. Keep the largest eligible energies and their sum.
If a bought particle is used with original particles, then , and each of those originals must have . The bought particle contributes a clean extra .
During the same sweep, store the sum of up to largest energies among originals with . Prefix-max this array, then a query is .
Research check: the official Codeforces problem page and the official Codeforces Round 1084 editorial point to the same intended idea: fix the final set size, sweep the reactivity threshold downward, and maintain top energies. The editorial page currently exposes hints/code more than prose, so the proof here is written from the supplied statement, which is the canonical source.
Let a chosen set contain particles. Every chosen particle must tolerate the other particles, so the condition is
for every chosen particle .
That is the main simplification. The reactor is basically a top- problem wearing a physics hat.
First solve the original particles only. Let , and define
.
For this threshold, any subset of at most particles from is valid, because each selected particle has at most others. Since all energies are positive, the best such subset is the largest up to values of inside . Let
sum of the largest up to energies among originals with .
Then the best answer without using any shop particle is
over .
Now handle a query particle . If Bessie buys it but does not use it, the answer is still . If she does use it with original particles, then the shop particle sees other particles, so . Also, each chosen original sees the shop particle plus the other originals, so each needs .
So for a fixed , the best partner sum is the largest up to original energies among particles with . Define
sum of the largest up to energies among originals with .
Then the best query answer that uses the shop particle is
.
Precompute the prefix maximum array , and each query becomes
.
Why does using up to instead of exactly not cheat? If uses only originals, then those originals all have , and a shop particle with also tolerates originals. So that subset is valid. Conversely, any valid query subset with originals is bounded by . No fake energy sneaks in.
To compute and , sort original particles by decreasing . Sweep from down to , inserting all particles that become eligible, meaning all particles with . Maintain a min-heap containing the largest up to inserted energies and a running sum cur.
After inserting newly eligible particles, pop the smallest kept energy while the heap size exceeds . This is safe because the capacity only decreases as goes down; once a value is too small to be kept, it will never become useful later. Future particles only add more competition. Brutal, but fair.
At threshold :
cur is , the sum of the largest up to eligible energies, so update base.cur if the heap size is at most , otherwise cur - heap.top().Edge cases:
max(base, ...).Complexity per test case is after sorting and heap operations, with memory. Across all tests this fits because total and total are at most .
Research used: official problem statement and official Codeforces editorial.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
void solve() {
int n, m;
cin >> n >> m;
vector<pair<int, ll>> a(n);
for (auto &[y, x] : a) {
cin >> x >> y;
}
sort(a.begin(), a.end(), [](const auto &p, const auto &q) {
return p.first > q.first;
});
priority_queue<ll, vector<ll>, greater<ll>> kept;
vector<ll> pref(n + 1, 0);
ll cur = 0, base = 0;
int ptr = 0;
for (int k = n; k >= 0; --k) {
while (ptr < n && a[ptr].first >= k) {
kept.push(a[ptr].second);
cur += a[ptr].second;
++ptr;
}
while ((int)kept.size() > k + 1) {
cur -= kept.top();
kept.pop();
}
base = max(base, cur);
pref[k] = ((int)kept.size() <= k ? cur : cur - kept.top());
}
for (int k = 1; k <= n; ++k) {
pref[k] = max(pref[k], pref[k - 1]);
}
for (int i = 0; i < m; ++i) {
ll x;
int y;
cin >> x >> y;
ll ans = max(base, pref[y] + x);
cout << ans << (i + 1 == m ? '\n' : ' ');
}
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
solve();
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
void solve() {
int n, m;
cin >> n >> m;
vector<pair<int, ll>> a(n);
for (auto &[y, x] : a) {
cin >> x >> y;
}
sort(a.begin(), a.end(), [](const auto &p, const auto &q) {
return p.first > q.first;
});
priority_queue<ll, vector<ll>, greater<ll>> kept;
vector<ll> pref(n + 1, 0);
ll cur = 0, base = 0;
int ptr = 0;
for (int k = n; k >= 0; --k) {
while (ptr < n && a[ptr].first >= k) {
kept.push(a[ptr].second);
cur += a[ptr].second;
++ptr;
}
while ((int)kept.size() > k + 1) {
cur -= kept.top();
kept.pop();
}
base = max(base, cur);
pref[k] = ((int)kept.size() <= k ? cur : cur - kept.top());
}
for (int k = 1; k <= n; ++k) {
pref[k] = max(pref[k], pref[k - 1]);
}
for (int i = 0; i < m; ++i) {
ll x;
int y;
cin >> x >> y;
ll ans = max(base, pref[y] + x);
cout << ans << (i + 1 == m ? '\n' : ' ');
}
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
solve();
}
}