CodeForces - 1257E (思惟)

题意

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;
}
相关文章
相关标签/搜索