cf1607 G. Banquet Preparations 1(贪心)
作者:互联网
https://codeforces.com/contest/1607/problem/G
题意:
给定数组a[],b[]
和整数m
。每个盘子里有ai个白球和bi个黑球。现要从每个盘子里拿走m
个球,使得剩下的所有白球的和与所有黑球的和的差的绝对值最小。题目保证每个盘子里的球数不少于m
思路:
假设从每个盘子里拿 \(x_i\) 个白球和 \(m-x_i\)个白球,那么最后这个差的绝对值就是
\[\left| \sum_{i=1}^n (a_i-x_i) - \sum_{i=1}^n (b_i-(m-x_i)) \right| = \left| \sum_{i=1}^n (a_i-b_i+m-2x_i) \right| \\ = \left| nm+\sum_{i=1}^n (a_i-b_i) - 2\sum_{i=1}^n x_i \right| =|s - 2sumx| \]每个 \(x_i\) 有最小值 \(mmin_i\) 和最大值 \(mmax_i\),所以 \(2sumx\) 也有最小值 \(2smin\) 和最大值 \(2smax\) 。而且 \(sumx\) 可以取到 \([smin, smax]\) 中的一切值!
如果 \(s >= 2smax\),答案就是 \(s-2smax\) ,每个盘子都要拿走 \(mmax_i\) 个白球;
如果 \(s <= 2smin\),答案就是 \(2smin-s\) ,每个盘子都要拿走 \(mmin_i\) 个白球;
如果 \(s\) 介于两者之间,那就先都拿 \(mmin_i\) 保底,然后贪心拿球逼近 \(s\) 。答案为0或1,取决于 \(s\) 的奇偶性
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const signed N = 2e5+10;
int mmax[N], mmin[N];
signed main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T; cin >> T; while(T--)
{
int n, m; cin >> n >> m;
ll s = (ll)m * n, smax=0, smin=0;
for(int i = 1; i <= n; i++)
{
int a, b; cin >> a >> b;
s += a - b;
smin += mmin[i] = max(0, m - b);
smax += mmax[i] = min(m, a);
}
if(s >= 2 * smax)
{
cout << s - 2 * smax << '\n';
for(int i = 1; i <= n; i++)
cout << mmax[i] << ' ' << m - mmax[i] << '\n';
}
else if(s <= 2 * smin)
{
cout << 2 * smin - s << '\n';
for(int i = 1; i <= n; i++)
cout << mmin[i] << ' ' << m - mmin[i] << '\n';
}
else
{
cout << s % 2 << '\n';
for(int i = 1; i <= n; i++)
{
int tmp = min((ll)mmax[i] - mmin[i], (s - 2 * smin) / 2);
smin += tmp;
tmp += mmin[i];
cout << tmp << ' ' << m - tmp << '\n';
}
}
}
return 0;
}
标签:mmax,int,sum,smax,Preparations,mmin,cf1607,白球,Banquet 来源: https://www.cnblogs.com/wushansinger/p/15547834.html