题意:一共有S元,给n个人分,每个人允许分到的钱数有一个范围( l ~ r ),可以不用完s,问最大的中位数是多少
思路:当时做到这里的时候宿舍也熄灯了,脑子还巨困。。。
比赛的时候想的是把全部人按照( l , r )排序,然后二分中间那个人的可分配范围,看最多能给这个人分配多少钱。
但是这么写有个问题,,,可能不用中间那个人作为中位数,如:
2 4 2 7 4 4 5 6 6 8这种情况下,如果按照我的思路是4,但是显然可以有,2,7,4,6,8。。。类似这种取法,原因在于 l 小的人可能 r 大,那么他可以取到更大的范围,这么排列就没啥用了!
昨天晚上一直在绞尽脑汁想到底按啥排序,但是其实有问题的是二分。。
二分的时候直接二分1--1e9,每次找出可以比这个值大的数有多少,大于n/2则可能成为中位数,然后贪心分配钱数就好了。
总结:。。还是想的太少
vector<pair<ll, ll> > v, v1;
void solve()
{
ll n, s,l, r, best;
ll low, high, mid, val, temp, flag;
rd(n),rd(s);v.clear();
val = n / 2 + 1;
for (int i = 0; i < n; i++)
{
rd(l),rd(r);
v.push_back({l, r});
}
sort(v.begin(), v.end());
low = 0;//
high = 1e9;//
while (low <= high)
{
flag = 1;
mid = (low + high) / 2;
v1.clear();
temp = 0;
for (int i = 0; i < v.size(); i++)
{
if (v[i].second >= mid)
v1.push_back(v[i]);
else
temp += v[i].first;
}
if (v1.size() < val) flag = 0;
else
{
ll idx = v1.size() - val;
for (int i = 0; i < v1.size(); i++)
{
if (i < idx)
temp += v1[i].first;
else
temp += max(mid, v1[i].first);
}
if (temp > s)
flag = 0;
}
if (flag)
best = mid,low = mid + 1;
else
high = mid - 1;
}
printf("%lld\n",best);
}
int main()
{
int t;rd(t);
while (t--)
solve();
return 0;
} 
京公网安备 11010502036488号