Cod sursa(job #2236770)

Utilizator Bodo171Bogdan Pop Bodo171 Data 30 august 2018 15:29:37
Problema Ghiozdan Scor 62
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.13 kb
#include <iostream>
#include <fstream>
#include <deque>
using namespace std;
const int nmax=75005;
deque<int> d;
int dp[2][nmax],f1[nmax],f2[nmax];
int ap[205],opt[205];
int lim=200005;
int use,n,G,i,ans,x,j;
void recu(int lin,int cat)
{
    for(int i=0; i<=cat; i++)
        dp[use][i]=lim;
    for(int rest=0; rest<min(lin,cat+1); rest++)
    {
        d.clear();
        for(int i=rest; i<=cat; i+=lin)
        {
            if((!d.empty())&&i-d.front()>lin*ap[lin])
                d.pop_front();
            while((!d.empty())&&dp[1-use][i]-(i-rest)/lin<=dp[1-use][d.back()]-(d.back()-rest)/lin)
                d.pop_back();
            d.push_back(i);
            dp[use][i]=(i-d.front())/lin+dp[1-use][d.front()];
        }
    }
    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);
    for(int i=0;i<=odr-ost;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[use][ans]);
    for(i=1;i<=200;i++)
        for(j=opt[i-1]+i;j<=opt[i];j+=i)
            g<<i<<'\n';
    return 0;
}