洛谷 P7542 MALI 題解
阿新 • • 發佈:2021-10-11
又雙叒叕水了一篇題解...
題目簡述
對於兩個序列 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\)
所以,每次選擇最小和最大的配對可以得到最優解。
可惜直接排序時間複雜度不夠。
時間複雜度為 \(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\)
最壞時間複雜度為 \(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