一开始想法是先让钱少的人选,不够就拿公用资金,然后发现不行,因为有可能花了所有钱给他买一辆车,还不如给那些钱多但是差价少的人;于是改为从大到小再选一次,但是对称的问题是,钱多的也有可能出现上述问题。所以我就想大小各搜一遍,然后比较,事实证明,还是不行,因为还有可能是中间的取最大值,什么乱七八糟的想法。
贪心做得太多了,成傻子了,老是把问题简单化,毕竟是个div.2的d题。首先选车这个问题就想错了。如果能选k辆车,那么正确的姿势应该是选k个钱多的人,和k个租费少的车,然后一一对应,并用上共同资金。现在就有一个问题,确定k的值。
遍历一遍?呵呵……超时了。然后这个时候就会发现,如果你k辆车都租不到,还谈k+1个球啊,就是说,如果k不行,那么k之后的都不可以,是不是想到了什么?对,二分法。取中点,判断中点是否满足,如果满足,就选(k+1,r)区间再找,如果不满足,就是(l,k-1)再找,这样就可以降低复杂度了。虽然写的很蛋疼,但是做难题是有提升的,尤其是这种差一点就可以的题目。另外,是找到了买车的方法才找到的二分法,并不是刻意的套思想,也不是平白无故出来的想法。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
int b[100005], p[100005];
int max( int a, int b)
{
return a > b ? a : b;
}
int min( int a, int b)
{
return a < b ? a : b;
}
int main()
{
int i, j, m, n, ans, a, sum, pre, num, leap;
cin >> n >> m >> a;
for (i = 1; i <= n; i++)
scanf("%d", &b[i]);
for (i = 1; i <= m; i++)
scanf("%d", &p[i]);
sort(b + 1, b + 1 + n);
sort(p + 1, p + 1 + m);
int l, r, mid;
l = 0; r = min(n, m); mid = (l + r) / 2; sum = 0;
while (l<=r)
{
leap = 0;
pre = a;
for (i = 1; i <= mid; i++)
{
if (b[n - mid + i] >= p[i])continue;
else if (b[n - mid + i] + pre >= p[i])
{
pre = pre - (p[i] - b[n - mid + i]);
}
else if (b[n - mid + i] + pre < p[i])
{
leap = 1; break;
}
}
if (leap)
{
r = mid - 1;
mid = (l + r) / 2;
}
else
{
sum = max(sum, mid);
l = mid + 1;
mid = (l + r) / 2;
}
}
num = -a;
for (i = 1; i <= sum; i++)
num = num + p[i];
cout << sum << " " << max(0, num) << endl;
return 0;
}