G-Game of Swapping Numbers
阿新 • • 發佈:2021-07-21
Game of Swapping Numbers
題意
給定兩個長度為\(n\)的陣列\(a、b\),計算\(\sum_{i=1}^n\mid a_i-b_i\mid\)。現要對\(a\)陣列中任意兩個元素交換位置,經過\(k\)次操作,輸出能夠獲取到的最大值。
思路
假設給定陣列\(a=\left\{2,8,9\right\}\),\(b=\left\{7,6,10\right\}\),在數軸上畫出
如果想要使得獲取到的值變大,我們就要想什麼樣的區間是對我們有益的。從上圖我們可以看出,對於\((6,8),(9,10)\)兩個沒有交集的區間,無論我們如何交換兩個區間的端點,區間的間隔都將會加入結果中,也就是我們可以獲取更大的值。而對於區間\((2,7),(6,8)\)
由於題目存在交換次數的限制,所以我們還需要考慮次數的影響。由於當\(n>2\)時,根據抽屜原理,\(a_i>b_i\)或者\(a_i<b_i\)中的一種情況必然出現兩次,因此對於至多\(k\)次操作是等價於必須\(k\)次操作的,因為我們只需要不斷交換兩個同一情況的區間,直到交換次數達到\(k\)次。而當\(n==2\)時,我們只需要對\(k\)的奇偶性進行判斷是否需要交換即可。
因此,我們只需要用兩個資料分別儲存\(min(a_i,b_i),max(a_i,b_i)\)
參考程式碼
點此展開
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef pair<int,int> PII; const int N=5e5+10; ll n,k; ll a[N],b[N]; ll u[N],d[N];//u[i]儲存較小值,d[i]儲存較大值 bool cmp(const ll &l,const ll &r) { return l>r; } int main() { cin>>n>>k; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++) cin>>b[i]; ll res=0;//注意結果可能很大 for(int i=1;i<=n;i++) { res+=abs(a[i]-b[i]); u[i]=min(a[i],b[i]); d[i]=max(a[i],b[i]); } if(n==2) { if(k&1) swap(a[1],a[2]); res=abs(a[1]-b[1])+abs(a[2]-b[2]); cout<<res<<endl; return 0; } sort(u+1,u+n+1,cmp); sort(d+1,d+n+1); for(int i=1;i<=min(n,k);i++) { if(u[i]>d[i]) res+=2*(u[i]-d[i]); else break; } cout<<res<<endl; return 0; }