专栏文章

题解:P14029 【MX-X20-T3】「FAOI-R7」重排序列(update)

P14029题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minwk9pm
此快照首次捕获于
2025/12/02 09:31
3 个月前
此快照最后确认于
2025/12/02 09:31
3 个月前
查看原文
该做法与第一篇题解略有不同。
已知 (a+b)modm=(amodm)+(bmodm)modm (a+b) \bmod m = (a \bmod m) + (b \bmod m ) \bmod m,我们将 a,ba,b 序列中所有数对 mm 取模,那么 ai+bia_i+b_i 的值域为 [0,2m][0,2m]
理想情况下,对于所有 iiai+bi<ma_i+b_i<m,那么和为 in(ai+bi)\sum^n_i (a_i+b_i)。但显然我们可能会有某些位置 iiai+bima_i+b_i \ge m,此时贡献变成了 ai+bima_i+b_i-m。对比理想状况,位置 ii 产生的贡献减少了 (ai+bi)(ai+bim)=m(a_i+b_i)-(a_i+b_i-m) = mmm 是给定常数,问题就转化成如何排列使得 a+bma+b \ge m 的情况最少。
aa 降序排序,bb 升序排序,aia_i 在递减过程中,bb 中满足 ai+bj<ma_i+b_j<m 的区间会向右扩展,我们不难发现此时 aia_i 去匹配最小的 bjb_j 是最优的。如果 aia_i 怎么匹配都匹配不到 ai+aj<ma_i+a_j<m,那就只能去和最大的 bjb_j 匹配,将更小的 bjb_j 留给后面的数。
时间复杂度 O(nlogn)O(n \log n)
CPP
# include <bits/stdc++.h>

using namespace std;

struct arr{
	long long v;
	long long new_v;
	int idx;
};
arr arr1[200005];
arr arr2[200005];

bool cmp1(arr a,arr b) {return a.new_v > b.new_v;}
bool cmp2(arr a,arr b) {return a.new_v < b.new_v;}
bool cmp3(arr a,arr b) {return a.idx < b.idx;}

void solve()
{
	int n,m;
	scanf ("%d %d",&n,&m);
	
	for (int i=0;i<n;i++) scanf ("%lld",&arr1[i].v);
	for (int i=0;i<n;i++) scanf ("%lld",&arr2[i].v);
	for (int i=0;i<n;i++) 
	{
		arr1[i].idx = i;
		arr2[i].idx = i;
		arr1[i].new_v=arr1[i].v%m;
		arr2[i].new_v=arr2[i].v%m;
	}
	
	sort(arr1,arr1+n,cmp1);
	sort(arr2,arr2+n,cmp2);
	
	long long ans=0;
	int l=0,r=n-1;
	for (int i=0;i<n;i++)
	{
		if (arr1[i].new_v + arr2[l].new_v >= m) 
		{
			ans += (arr1[i].new_v + arr2[r].new_v) % m;
			arr2[r--].idx = arr1[i].idx;	
		}
		else
		{
			ans += (arr1[i].new_v + arr2[l].new_v) % m;
			arr2[l++].idx = arr1[i].idx;
		}
	}
	
	sort(arr2,arr2+n,cmp3);
	
	printf ("%lld\n",ans);
	for (int i=0;i<n;i++) printf ("%lld ",arr2[i].v);
	printf ("\n");
	return ;
}

int main (void)
{
	int T;
	scanf ("%d",&T);
	
	while (T--)
	{
		solve();	
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...