AT-AGC018-C 题解
科技:
wqs 二分(板子)
思路:
首先,
设二维背包
然后,我们不难证明
考虑归纳。初始时,只有
因此,我们可以先用 wqs 二分把问题从三维降至二维,变成只限制一种币取的个数。我们不妨限制银币恰好取
这个问题简单贪心即可:我们可以把所有人按
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int N = 1e5 + 5;
int n,x,y,z,cnt,a[N],b[N],c[N];
struct Node{int w1,w2,t;} p[N];
bool cmp(Node x,Node y)
{
if(x.w2 - x.w1 != y.w2 - y.w1) return x.w2 - x.w1 > y.w2 - y.w1;
return x.t < y.t;
}
ll check(int k)
{
ll ret = 0;
cnt = 0;
for(int i = 1;i <= n;i++)
{
if(a[i] - k >= c[i]) p[i].w1 = a[i] - k,p[i].t = 1;
else p[i].w1 = c[i],p[i].t = 0;
p[i].w2 = b[i];
}
sort(p + 1,p + n + 1,cmp);
for(int i = 1;i <= y;i++) ret += p[i].w2;
for(int i = y + 1;i <= n;i++) ret += p[i].w1,cnt += p[i].t;
return ret;
}
int main()
{
scanf("%d%d%d",&x,&y,&z);
n = x + y + z;
for(int i = 1;i <= n;i++) scanf("%d%d%d",&a[i],&b[i],&c[i]);
int l = -1e9,r = 1e9,mid;
while(r - l > 1)
{
mid = ((l + r) >> 1);
check(mid);
if(cnt >= x) l = mid;
else r = mid;
}
printf("%lld\n",check(l) + 1LL * l * x);
return 0;
}