Cod sursa(job #2036929)

Utilizator robx12lnLinca Robert robx12ln Data 11 octombrie 2017 14:13:32
Problema Ghiozdan Scor 96
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.26 kb
#include<fstream>
#include<cstring>
#define INF 1000000
using namespace std;
ifstream fin("ghiozdan.in");
ofstream fout("ghiozdan.out");
int f[205], D[2][75005], T[2][75005], p, u, deq[20005], ok;
void solve( int st, int dr, int G ){

    if( G == 0 )
        return;

    if( st == dr ){
        int nr = f[st];
        while( nr != 0 && G != 0 ){
            fout << st << "\n";
            nr--;
            G -= st;
        }
        return;
    }

    for( int i = 0; i <= G; i++ ){
        D[0][i] = D[1][i] = INF;
    }

    int mid = ( st + dr ) / 2;

    ok = 1;
    for( int i = st; i <= dr; i++ ){

        if( f[i] == 0 )
            continue;

        D[!ok][0] = 0;
        D[ok][1] = 0;
        for( int j = 0; j < i; j++ ){
            D[ok][j] = D[!ok][j];
        }
        for( int r = 0; r < i; r++ ){
            p = 1;
            u = 0;
            for( int j = i + r; j <= G; j += i ){
                D[ok][j] = D[!ok][j];
                if( D[!ok][j] != INF )
                    T[ok][j] = ( i <= mid ) ? j : T[!ok][j];

                if( D[!ok][j - i] != INF ){
                    while( p <= u && D[!ok][j - i] < D[!ok][ deq[u] ] + ( j - deq[u] ) / i )
                        u--;
                    deq[++u] = j - i;
                }
                if( ( j - deq[p] ) / i > f[i] )
                    p++;

                if( p <= u && D[ok][j] > D[!ok][ deq[p] ] + ( j - deq[p] ) / i ){
                    D[ok][j] = D[!ok][ deq[p] ] + ( j - deq[p] ) / i;
                    T[ok][j] = ( i <= mid ) ? j : T[!ok][ deq[p] ];
                }

            }

        }
        ok = !ok;
        for( int i = 0; i <= G; i++ )
            D[ok][i] = INF;
    }

    ok = !ok;

    int val = 0;
    for( int i = G; i >= 1; i-- ){
        if( D[ok][i] != INF ){
            val = i;
            break;
        }
    }

    if( st == 1 && dr == 200 ){
        fout << val << " " << D[ok][val] << "\n";
    }
    int save = T[ok][val];
    solve( st, mid, save );
    solve( mid + 1, dr, val - save );

}
int main(){
    int n, G;
    fin >> n >> G;
    for( int i = 1; i <= n; i++ ){
        int x;
        fin >> x;
        f[x]++;
    }
    solve( 1, 200, G );
    return 0;
}