https://vjudge.net/problem/CodeForces-1257Ehtml
三我的,每一個人有一些數字,組合起來是1~n,每一個人能夠給另外一我的一個擁有的數字,問最小操做數,使得第一我的擁有1~i的數,第二我的擁有i+1~j的數,第三我的擁有j+1~n的數,即第一我的爲前綴,第二我的爲中間部分,第三我的爲後綴。 注意:能夠有一個或兩我的最後不擁有數字。ios
先把問題簡單化,考慮只有兩我的的狀況。設cnt1[x]表示第一我的前x個數擁有的個數,cnt2[x]表示第二我的前x個數擁有的個數,若是第一我的得到的前綴爲1~i,第二我的得到的後綴爲i+1~n,那麼代價爲cnt2[i]+cnt1[n]-cnt1[i]。c++
再考慮三我的的狀況,一樣,若是第一我的得到1~i,第二我的得到i+1~j,第三我的得到j+1~n,那麼代價爲cnt2[i]+cnt3[i] +cnt1[j]-cnt1[i]+cnt3[j]-cnt3[i] + cnt1[n]-cnt1[j]+cnt2[n]-cnt2[j],化簡得:cnt2[i]-cnt1[i]+cnt3[j]+cnt1[n]+cnt2[n]-cnt2[j],即cnt2[i]-cnt1[i] + cnt1[n]+cnt2[n] + cnt3[j]-cnt2[j],因此枚舉i,使這個式子值最小,發現還剩下兩個和j有關的項對式子有影響,而j>=i,因而問題轉化成了枚舉i,求cnt2[i]-cnt1[i]+min(cnt3[i~n]-cnt2[i~n])+cnt1[n]+cnt2[n],咱們只用維護cnt3[j]-cnt2[j]的後綴最小值便可。spa
注意:由於可能有一我的或兩我的沒有任何數,那麼此時i和j是能夠相等的,好比i==j時第二我的沒有數,i==j==0時第一、2我的沒有數,i==j==n時第2、三我的沒有數,i==0&&j==n時第一、3我的沒有數,等等狀況.net
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define ll long long const int N=200005; const int mod=1e9+7; const double eps=1e-8; const double PI = acos(-1.0); #define lowbit(x) (x&(-x)) int a[4][N]; int c[4][N],mn[N]; int main() { std::ios::sync_with_stdio(false); int k1,k2,k3; cin>>k1>>k2>>k3; int n=k1+k2+k3; for(int i=1;i<=k1;i++) { cin>>a[1][i]; ++c[1][a[1][i]]; } for(int i=1;i<=k2;i++) { cin>>a[2][i]; ++c[2][a[2][i]]; } for(int i=1;i<=k3;i++) { cin>>a[3][i]; ++c[3][a[3][i]]; } for(int i=1;i<=n;i++) { for(int j=1;j<=3;j++) { c[j][i]+=c[j][i-1]; } } mn[n+1]=inf; for(int i=n;i>=0;i--) { mn[i]=min(mn[i+1],c[3][i]-c[2][i]); } int ans=inf; for(int i=0;i<=n;i++) { ans=min(ans,c[2][i]-c[1][i]+mn[i]+c[1][n]+c[2][n]); // cout<<i<<" "<<ans<<endl; } cout<<ans<<endl; return 0; }