Cod sursa(job #2225993)

Utilizator SebiSebiPirtoaca George Sebastian SebiSebi Data 29 iulie 2018 04:34:18
Problema Ghiozdan Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.49 kb
#include <iostream>
#include <fstream>
#include <algorithm>
#include <string.h>
#include <assert.h>
#include <vector>
using namespace std;

#define GMAX 75001
#define NMAX 201
#define INF (1 << 30)

int ap[NMAX];
int sol[GMAX], sol_aux[GMAX], diff[GMAX], deq[GMAX], /* until mij */ um[GMAX], um_aux[GMAX];
vector <int> obj;

void compute(int st, int dr, int g) {
    int i, j, cnt;
    if (g == 0 || st > dr)
        return;
    if (st == dr) {
        assert(g % st == 0);
        for (int i = st; i <= g; i += st)
            obj.push_back(st);
        return;
    }

    int mij = (st + dr) / 2;

    for (i = 1; i <= g; i++) {
        sol[i] = -1;
        um[i] = -1;
    }
    sol[0] = 0;
    um[0] = 0;

    /*
     * Which is the sum of the objects in an optimal solution whose
     * weights are <= mij;
     */
    for (j = st; j <= dr; j++) {
        if (ap[j] > 0) {
            cnt = ap[j];
            memset(sol_aux, 0, sizeof(sol_aux));
            memset(um_aux, 0, sizeof(um_aux));
            for (int off = 0; off <= j - 1; off++) {
                {
                    int k = 0;
                    for (i = off; i <= g; i += j) {
                        diff[i] = sol[i] - k;
                        if (sol[i] == -1)
                            diff[i] = INF;
                        k++;
                    }
                }
                {
                    int k = 0, st = 1, dr = 0;
                    for (i = off; i <= g; i += j) {
                        while (st <= dr && diff[i] <= diff[deq[dr]])
                            dr--;
                        deq[++dr] = i;
                        int idx = (int)max(0LL, 0LL + i - 1LL * cnt * j);
                        while (deq[st] < idx)
                            st++;
                        if (diff[deq[st]] == INF) {
                            sol_aux[i] = -1;
                            um_aux[i] = -1;
                        }
                        else {
                            sol_aux[i] = diff[deq[st]] + k;
                            um_aux[i] = um[deq[st]];
                        }
                        k++;
                    }
                }
            }
            for (i = 0; i <= g; i++)
                sol[i] = sol_aux[i];
            if (j <= mij) {
                for (i = 0; i <= g; i++) {
                    if (sol[i] == -1)
                        um[i] = -1;
                    else
                        um[i] = i;
                }
            }
            else {
                for (i = 0; i <= g; i++) {
                    um[i] = um_aux[i];
                }
            }
        }
    }

    for (i = g; i >= 0; i--) {
        if (sol[i] != -1)
            break;
    }

    int x = um[i];
    compute(st, mij, x);
    compute(mij + 1, dr, g - x);
}

int main () {
    ios::sync_with_stdio(false);
    int n, g, i, cnt, j;

    ifstream f("ghiozdan.in");
    ofstream G("ghiozdan.out");

    f >> n >> g;
    for (i = 1; i <= n; i++) {
        int x;
        f >> x;
        ap[x]++;
    }
    f.close();

    for (i = 1; i <= g; i++) {
        sol[i] = -1;
    }
    sol[0] = 0;

    for (j = 1; j <= NMAX - 1; j++) {
        if (ap[j] == 0)
            continue;
        cnt = ap[j];
        memset(sol_aux, 0, sizeof(sol_aux));
        for (int off = 0; off <= j - 1; off++) {
            {
                int k = 0;
                for (i = off; i <= g; i += j) {
                    diff[i] = sol[i] - k;
                    if (sol[i] == -1)
                        diff[i] = INF;
                    k++;
                }
            }
            {
                int k = 0, st = 1, dr = 0;
                for (i = off; i <= g; i += j) {
                    while (st <= dr && diff[i] <= diff[deq[dr]])
                        dr--;
                    deq[++dr] = i;
                    int idx = (int)max(0LL, 0LL + i - 1LL * cnt * j);
                    while (deq[st] < idx)
                        st++;
                    if (diff[deq[st]] == INF)
                        sol_aux[i] = -1;
                    else
                        sol_aux[i] = diff[deq[st]] + k;
                    k++;
                }
            }
        }
        for (i = 0; i <= g; i++)
            sol[i] = sol_aux[i];
    }

    for (i = g; i >= 0; i--) {
        if (sol[i] != -1)
            break;
    }

    assert(i >= 0);

    G << i << " " << sol[i] << '\n';
    compute(1, NMAX - 1, i);
    for (vector <int> :: iterator it = obj.begin(); it != obj.end(); it++) {
        G << *it << '\n';
    }
    G.close();
    return 0;
}