Cod sursa(job #2236812)

Utilizator Bodo171Bogdan Pop Bodo171 Data 30 august 2018 16:44:24
Problema Ghiozdan Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 2.05 kb
#include <iostream>
#include <fstream>
#include <deque>
using namespace std;
const int nmax=75005;
int d[nmax];
int dp[2][nmax],f1[nmax],f2[nmax];
int ap[205],opt[205];
int lim=200005;
int use,n,G,i,ans,x,j,p,u;
void recu(int lin,int cat)
{
    for(int rest=0; rest<min(lin,cat+1); rest++)
    {
        p=1;u=0;
        for(int i=0; i*lin+rest<=cat; i++)
        {
            if(p<=u&&i-d[p]>ap[lin])
               p++;
            while(p<=u&&dp[1-use][i*lin+rest]-i<=dp[1-use][d[u]*lin+rest]-d[u])
                u--;
            d[++u]=i;
            dp[use][i*lin+rest]=i-d[p]+dp[1-use][d[p]*lin+rest];
        }
    }
    use=1-use;
}
void get_best(int l,int r,int cat)
{
    for(int i=0;i<=cat;i++)
        dp[0][i]=lim;
    dp[0][0]=0;
    use=1;
    for(int lin=l;lin<=r;lin++)
        recu(lin,cat);
    for(int i=0;i<=cat;i++)
        f1[i]=dp[1-use][i];
}
void get_best_rev(int l,int r,int cat)
{
    for(int i=0;i<=cat;i++)
        dp[0][i]=lim;
    dp[0][0]=0;
    use=1;
    for(int lin=r;lin>=l;lin--)
        recu(lin,cat);
    for(int i=0;i<=cat;i++)
        f2[i]=dp[1-use][i];
}
void divide(int l,int r,int ost,int odr,int expected)
{
    int m=(l+r)/2;
    if(l>r)
        return;
    if(l==r)
    {
        opt[m]=odr;
        return;
    }
    get_best(l,m,odr-ost);
    get_best_rev(m+1,r,odr-ost);
    opt[m]=-1;
    for(int i=0;i<=odr-ost&&opt[m]==-1;i++)
    {
        if(f1[i]+f2[odr-ost-i]==expected)
                opt[m]=i+ost;
    }
    int v1=f1[opt[m]-ost],v2=f2[odr-opt[m]];
    divide(l,m,ost,opt[m],v1);
    divide(m+1,r,opt[m],odr,v2);
}
int main()
{
    ifstream f("ghiozdan.in");
    ofstream g("ghiozdan.out");
    f>>n>>G;
    for(i=1;i<=n;i++)
    {
        f>>x;
        ap[x]+=1;
    }
    get_best(1,200,G);
    for(i=0;i<=G;i++)
        if(dp[1-use][i]<=n)
            ans=i;
    g<<ans<<' '<<dp[1-use][ans]<<'\n';
    divide(1,200,0,ans,dp[1-use][ans]);
    for(i=1;i<=200;i++)
        for(j=opt[i-1]+i;j<=opt[i];j+=i)
            g<<i<<'\n';
    return 0;
}