Cod sursa(job #18084)

Utilizator dominoMircea Pasoi domino Data 18 februarie 2007 02:50:30
Problema Ghiozdan Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.56 kb
#include <stdio.h>

#define MAX_G 75005
#define FIN "ghiozdan.in"
#define FOUT "ghiozdan.out"
#define INF 0x3f3f3f3f

int N, G, cnt[256], Q[MAX_G], V[MAX_G], bst[2][MAX_G], up[2][MAX_G];

void solve(int l, int r, int w)
{
    int i, j, k, ql, qr, idx, prev, m = (l+r)/2;

    if (!w) return;
    if (l == r)
    {
        for (i = 0; i < cnt[l] && i*l < w; i++)
            printf("%d\n", l);
        return;
    }

    bst[0][0] = 0;
    for (i = 1; i <= w; i++) bst[0][i] = INF;

    for (i = l, idx = 0; i <= r; i++)
    {
        if (!cnt[i]) continue;
        prev = idx; idx = !idx;
        for (j = 0; j < i; j++)
            for (k = j, ql = 0, qr = -1; k <= w; k += i)
            {   
                for (; ql <= qr && Q[ql] < k-cnt[i]*i; ql++);
                for (; ql <= qr && V[qr] >= bst[prev][k]-(k/i); qr--);
                Q[++qr] = k; V[qr] = bst[prev][k]-(k/i);
                if (ql <= qr)
                {
                    bst[idx][k] = bst[prev][Q[ql]]+(k-Q[ql])/i;
                    up[idx][k] = i <= m ? k : up[prev][Q[ql]];
                }
            }
    }

    for (i = w; i >= 0 && bst[idx][i] >= INF; i--);
    if (l == 1 && r == 200) printf("%d %d\n", i, bst[idx][i]);
    i = up[idx][i];

    solve(l, m, i); 
    solve(m+1, r, w-i);
}

int main(void)
{
    int i, x;

    freopen(FIN, "r", stdin);
    freopen(FOUT, "w", stdout);

    scanf("%d %d", &N, &G);
    for (i = 0; i < N; i++)
    {
        scanf("%d", &x);
        cnt[x]++;
    }
    solve(1, 200, G);

    return 0;
}