题解:P4765 [CERC2014] The Imp
模拟赛 T3,但是
很容易想到这个题复杂度是
首先有个结论:对于所有要选的货物,
考虑两个货物,价格分别是
很显然
我们考虑设计 dp,令
注意
#include<bits/stdc++.h>
using namespace std;
#define I inline
#define int long long
namespace SlowIO {
const int SZ = (1 << 20) + 1;
char buf[SZ], *p1 = buf, *p2 = buf;
char buffer[SZ];
int op1 = -1;
const int op2 = SZ - 1;
I char gc() {
if(p1 != p2) return *p1++;
return p1 == (p2 = (p1 = buf) + fread(buf, 1, SZ - 1, stdin)) ? EOF : *p1++;
}
I void flush() {
fwrite(buffer, 1, op1 + 1, stdout);
op1 = -1;
}
I void pc(const char &x) {
if(op1 == op2) flush();
buffer[++op1] = x;
}
I int read() {
int x = 0, f = 1; char ch = gc();
while(ch < '0' || ch > '9') {if(ch == '-') f = -f; ch = gc();}
while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ 48), ch = gc();
return x * f;
}
I void write(int x) {
if(x < 0) pc('-'), x = -x;
if(!x) {pc('0'); return ;}
char s[25];
int tot = 0;
while(x || !tot) {
s[tot++] = x % 10 + 48;
x/=10;
}
while(tot--) pc(s[tot]);
}
} using namespace SlowIO;
const int N = 150010;
int n, m;
int dp[N][22];
struct node {
int A, B;
} a[N], b[N];
bool cmp(node a, node b) {
return a.B > b.B;
}
signed main() {
int T = read();
while(T--) {
n = read(), m = read();
for(int i = 1; i <= n; i++) a[i].B = read(), a[i].A = read();
sort(a + 1, a + 1 + n, cmp);
for(int i = 1; i <= n; i++) {
dp[i][0] = max(dp[i - 1][0], a[i].B - a[i].A);
for(int j = 1; j <= m; j++) {
dp[i][j] = max(dp[i - 1][j], min(dp[i - 1][j - 1] - a[i].A, a[i].B - a[i].A));
}
}
write(dp[n][m]); pc('\n');
}
flush();
return 0;
}
但是模拟赛题的数据被 A_zjzj 加强成了
正解是反悔贪心。
继续沿用前面的结论:对于所有要选的货物,
考虑二分答案。
只要我们能够选出选出
然后如果物品可行就直接加,否则考虑反悔,和前面加入的最贵的弹出去。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 150010;
int n, m;
struct node {
int A, B;
} a[N];
bool cmp(node a, node b) {
return a.B < b.B;
}
bool chk(int mid) {
priority_queue<int> q;
while(!q.empty()) q.pop();
int sum = 0, cnt = 0;
for(int i = 1; i <= n; i++) {
if(a[i].B - a[i].A - sum >= mid) {
cnt++;
sum += a[i].A;
q.push(a[i].A);
}
else {
if(!q.empty() && q.top() > a[i].A) {
sum -= q.top();
sum += a[i].A;
q.pop(); q.push(a[i].A);
}
}
if(cnt == m + 1) return 1;
}
return 0;
}
signed main() {
ios::sync_with_stdio(0);
int T; cin >> T;
while(T--) {
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i].B >> a[i].A;
sort(a + 1, a + 1 + n, cmp);
int l = 1, r = 1e18, ans = 0;
while(l <= r) {
int mid = l + r >> 1;
if(chk(mid)) ans = mid, l = mid + 1;
else r = mid - 1;
}
cout << ans << '\n';
}
return 0;
}