test 190801 codechef Partition into Permutations

http://www.codechef.com/download/translated/LTIME70/mandarin/PERMPART.pdf

Apparently only greater than or equal $ 2 * N $ number may be left

Suppose S_I $ $ $ i represents the number of occurrences in the original sequence $

It can be converted to the original problem: find such a sequence $ b $, satisfy $ \ sum_ {i = 1} ^ {2 * N} {| s_i-b_i |} $ is minimal, $ b $ does not rise

It is easy to think of $ n ^ 2 $ dynamic regulation

Provided $ dp_ {i, j} $ represents a minimum cost Before considering the number of $ I $, $ b_i = j $ first when

$ Dp_ {i, j} = min (dp_ {i-1, k}) + abs (s_i-j) $, where $ k \ geq j $, and then rolling the array optimization

The examination room thought so much

In fact, there is an obvious place: $ b_i \ leq \ frac {2 * N} {i} $

Such complexity is $ (nlog_2 {n}) O $

 

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,a[N],s[N<<1];
long long f[2][N<<1];
long long ans;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<=n<<1;++i) s[i]=0;
        ans=0;
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
            if(a[i]>n<<1) ++ans;
            else ++s[a[i]];
        }
        for(int i=1;i<=n<<1;++i)
        {
            long long minx=1e16;
            if(i>1)
                for(int j=(n<<1)/(i-1);j>(n<<1)/i;--j)
                    minx=min(minx,f[(i-1)&1][j]);
            else minx=0;
            for(int j=(n<<1)/i;j>=0;--j)
                minx=min(minx,f[(i-1)&1][j]),f[i&1][j]=minx+abs(s[i]-j);
        }
        printf("%lld\n",ans+min(f[0][1],f[0][0]));
    }
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/w19567/p/11283264.html