Cod sursa(job #2224319)

Utilizator LucianTLucian Trepteanu LucianT Data 23 iulie 2018 18:28:08
Problema Ghiozdan Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.34 kb
#include <bits/stdc++.h>
using namespace std;

const int maxN=2e4+4;
const int maxG=75005;
const int maxVal=200;
const int INF=1<<30;

int fq[maxVal+1];

int deq[maxG];
int t[2][maxG];
int dp[2][maxG];

int n,g;

void solve(int st,int dr,int g)
{
    if(g==0)
        return;

    if(st==dr){
        for(int i=1;i<=fq[st] && g-st>=0;i++){
            printf("%d\n",st);
            g-=st;
        }
        return;
    }

    int mij=(st+dr)/2;
    for(int i=0;i<2;i++)
        for(int j=0;j<=g;j++)
            dp[i][j]=INF;

    int now=1;
    dp[0][0]=0;
    for(int i=st;i<=dr;i++)
        if(fq[i])
        {
            dp[0][0]=dp[1][0]=0;

            for(int r=i;r>=1;r--)
            {
                int lef=1,rig=0;

                for(int j=r;j<=g;j+=i)
                {
                    dp[now][j]=dp[now^1][j];

                    if(dp[now][j]<INF)
                        if(i<=mij)
                            t[now][j]=j;
                        else t[now][j]=t[now^1][j];

                    if(j>=i && dp[now^1][j-i]<INF){
                        while(lef<=rig && dp[now^1][j-i]<dp[now^1][deq[rig]]+(j-i-deq[rig])/i)
                            rig--;
                        deq[++rig]=j-i;
                    }

                    if((j-deq[lef])/i > fq[i])
                        lef++;

                    if(lef<=rig && dp[now][j]>dp[now^1][deq[lef]]+(j-deq[lef])/i)
                    {
                        dp[now][j]=dp[now^1][deq[lef]]+(j-deq[lef])/i;
                        if(i<=mij)
                            t[now][j]=j;
                        else
                            t[now][j]=t[now^1][deq[lef]];
                    }
                }
            }

            now^=1;
        }

    int split=-1,bst=0;
    for(int i=g;i>=1;i--)
        if(dp[now^1][i]<INF){
            split=t[now^1][i];
            bst=i;
            break;
        }

    if(st==1 && dr==maxVal)
        printf("%d %d\n",bst,dp[now^1][bst]);

    solve(st,mij,split);
    solve(mij+1,dr,bst-split);
}

int main()
{
    freopen("ghiozdan.in","r",stdin);
    freopen("ghiozdan.out","w",stdout);

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

    solve(1,maxVal,g);

    return 0;
}