Warning: session_start(): open(/tmp/sess_6a1c0ab9a3dbc23241f4fe7923c35ae2, O_RDWR) failed: No space left on device (28) in /data/wiki/inc/init.php on line 239

Warning: session_start(): Failed to read session data: files (path: ) in /data/wiki/inc/init.php on line 239

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/inc/auth.php on line 430

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/inc/actions.php on line 38

Warning: Cannot modify header information - headers already sent by (output started at /data/wiki/inc/init.php:239) in /data/wiki/lib/tpl/dokuwiki/main.php on line 12
2020-2021:teams:legal_string:组队训练比赛记录:contest3 [CVBB ACM Team]

用户工具

站点工具


2020-2021:teams:legal_string:组队训练比赛记录:contest3

比赛链接

题解

G. Game of Swapping Numbers

题意

给定两个长度为 $n$ 的序列 $A,B$ 和 $k$ 次操作,每次操作可以交换 $a_i,a_j$。

要求在 $k$ 次操作后最小化 $\sum_{i=1}^n|a_i-b_i|$。

题解

首先考虑不存在 $k$ 约束的情况。

可以将本题转化为从 $a_i,b_i$ 中选定 $n$ 个数在前面加上 $+$ 号,其余 $n$ 个数在前面加上 $-$ 号。最后需要最大化所有带符号数的和。

显然贪心选取 $a_i,b_i$ 这 $2n$ 个数中前 $n$ 大加上 $+$ 号即可。然后为了保证合法性,需要使得 $a_i,b_i$ 正好一正一负。

于是考虑任选一组 $(+a_i,+b_i),(-a_j,-b_j)$,交换 $a_i,a_j$ 直到不存在这种情况为止即可。

接下来考虑 $k$ 有限的情况,显然贪心每次选取收益最大的 $(+a_i,+b_i),(-a_j,-b_j)$ 交换即可。

此时收益为 $2(\min(a_i,b_i)-\max(a_j,b_j))$,于是考虑将 $\min(a_i,b_i)$ 序列从大到小排序,$\max(a_i,b_i)$ 从小到大排序。

然后贪心取前 $k$ 个收益即可。注意 $(+a_i,+b_i)$ 在 $\min(a_i,b_i)$ 序列中一定排在 $(+a_i,-b_i),(-a_i,+b_i),(-a_i,-b_i)$ 的前面。

注意 $(-a_i,-b_i)$ 在 $\max(a_i,b_i)$ 序列中一定排在 $(+a_i,-b_i),(-a_i,+b_i),(+a_i,+b_i)$ 的前面。

于是一定会先让所有 $(+a_i,+b_i)$ 和 $(-a_j,-b_j)$ 配对,至于其他的配对方案计算出来的 $2(\min(a_i,b_i)-\max(a_j,b_j))$ 都是非正数,可以舍去。

注意到 $k$ 可能大于需要交换的次数,但此时如果 $n\gt 2$ 一定可以找到两个同号的 $a_i,a_j$ 做无意义的交换消耗 $k$,使得 $k$ 正好等于需要交换的次数。

最后 $n=2$ 的情况没有选择只能强制交换,所以不一定可以得到最优解,需要特判。总时间复杂度 $O(n\log n)$。

查看代码

查看代码

const int MAXN=5e5+5;
int a[MAXN],b[MAXN];
int main()
{
	int n=read_int(),k=read_int();
	_for(i,0,n)a[i]=read_int();
	_for(i,0,n)b[i]=read_int();
	if(n==2){
		if(k&1)swap(a[0],a[1]);
		enter(abs(a[0]-b[0])+abs(a[1]-b[1]));
		return 0;
	}
	LL ans=0;
	_for(i,0,n){
		if(a[i]>b[i])
		swap(a[i],b[i]);
		ans+=b[i]-a[i];
	}
	sort(a,a+n,greater<int>());
	sort(b,b+n);
	_for(i,0,min(n,k))
	ans+=max(0,a[i]-b[i])*2;
	enter(ans);
	return 0;
}

赛后总结

jxm:玄学场,打表、随机化yyds

2020-2021/teams/legal_string/组队训练比赛记录/contest3.1626572692.txt.gz · 最后更改: 2021/07/18 09:44 由 jxm2001