1. 程式人生 > 其它 >洛谷 P7542 MALI 題解

洛谷 P7542 MALI 題解

又雙叒叕了一篇題解...

題目簡述

對於兩個序列 A,序列 B,長度一致;

\(n\) 次操作,

每次操作都會向這兩個序列增加數字。

在每次操作後,要求對每個序列中的每個數字配對,要讓配對數之和最大值最小

Solution

貪心。

對每時每刻的序列排序,\(a\)從小到大\(b\)從大到小配對。

證明:

對於序列中最小的 \(a_i\),序列最大的\(b_j\)

若將 \(a_i\) 替換成 \(a_k\)\(a_k>a_i\) ,此時必有 \(a_k+b_j>a_i+b_j\),不必原計劃更優;

若將 \(b_j\) 替換成 \(b_k\),且 \(b_j<b_k\)

,則必有 \(a_z>a_i\) 需要與 \(b_j\) 配對。所以必有更大值 \(a_z+b_j>a_i+b_j\),也不必原計劃更優。

所以,每次選擇最小和最大的配對可以得到最優解。

可惜直接排序時間複雜度不夠。

時間複雜度為 \(O(n^2\log n)\)\(n\leq 10^5\),超時。

優化。

1、桶優化

發現 \(1\leq a_i,b_j\leq 100\),所以考慮直接桶排。

時間複雜度降為 \(O(n^2)\)

2、連續配對優化

發現當 \(a_i,b_j\) 出現多次時,會直接配出 \(\min(a_i,b_j)\) 組一樣的配對。

所以對於桶中 \(a_i,b_j\)

,每次配對時,對應減少 \(\min(a_i,b_j)\) 即可。

最壞時間複雜度為 \(O(100n)\) ,不會超時。

AC Code

#include<bits/stdc++.h>
using namespace std;
int a[101],b[101];
int am[101],bm[101];

int main()
{
	int n,k,maxn=-414231;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		maxn=-414231;
		cin>>k,am[k]++;
		cin>>k,bm[k]++;  //優化1
		memcpy(a,am,sizeof(am));
		memcpy(b,bm,sizeof(bm)); //複製桶
		int l=1,r=100;
		while(r>=1&&l<=100)
		{
			while(!a[l]) l++;
			while(!b[r]) r--;
			if(r<1||l>100) break;
			maxn=max(maxn,l+r);
			minx=min(a[l],b[r]);
			a[l]-=minx;b[r]-=minx;  //優化2
		}
		cout<<maxn<<endl;
	}
	return 0;
}

qwq