Cod sursa(job #2052219)

Utilizator ionanghelinaIonut Anghelina ionanghelina Data 30 octombrie 2017 11:10:47
Problema Ghiozdan Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 2.29 kb
#include<bits/stdc++.h>
#define maxG 75005
#define inf 1000000000
using namespace std;
deque<int> q;
int dp[2][maxG],T[2][maxG],f[205];
inline void Solve(int st,int dr,int g)
{
    if(g<=0)
    {
        return ;
    }
    if(st==dr)
    {
        for(int i=1;i<=f[st] && g>=st;i++)
        {
            printf("%d\n",st);
            g-=st;
        }
        return;
    }

    int mid=(st+dr)>>1;

    for(int i=0;i<=g;i++)
        dp[0][i]=dp[1][i]=inf;

    int line=0;
    for(int i=st;i<=dr;i++)
    {
        if(!f[i]) continue;
        dp[0][0]=0;
        dp[1][0]=0;

        for(int rest=i;rest>=1;rest--)
        {
            q.clear();
            for(int j=rest;j<=g;j+=i)
            {
                dp[line][j]=dp[!line][j];
                if(dp[line][j]!=inf)
                {
                if( i<=mid)
                {
                    T[line][j]=j;
                }
                    else T[line][j]=T[!line][j];
                }
            if(j>=i && dp[!line][j-i]!=inf)
            {
                while(!q.empty() && dp[!line][j-i]<dp[!line][q.back()]+(j-i-q.back())/i)
                {
                    q.pop_back();
                }
                q.push_back(j-i);
            }
            while(!q.empty() && (j-q.front())/i>f[i]) q.pop_front();
            if(!q.empty())
            {
                if(dp[line][j]>(dp[!line][q.front()]+(j-q.front())/i))
                {
                    dp[line][j]=dp[!line][q.front()]+(j-q.front())/i;
                if(i<=mid)
                    T[line][j]=j;
                    else T[line][j]=T[!line][q.front()];
                }
            }
            }
        }
        line=1-line;
    }
    int sol=0;
    for(int i=g;i>=1;i--)
    {
        if(dp[!line][i]!=inf)
        {
            sol=i;
            break;
        }
    }
    if(st==1 && dr==200)
    {
        printf("%d %d\n",sol,dp[!line][sol]);
    }
    Solve(st,mid,T[!line][sol]);
    Solve(mid+1,dr,sol-T[!line][sol]);
}
int n,g,x;
int main()
{
    freopen("ghiozdan.in","r",stdin);
    freopen("ghiozdan.out","w",stdout);

    scanf("%d%d",&n,&g);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        f[x]++;
    }

    Solve(1,200,g);


    return 0;
}