Cod sursa(job #1829525)

Utilizator AlexNiuclaeNiculae Alexandru Vlad AlexNiuclae Data 15 decembrie 2016 09:30:59
Problema Ghiozdan Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.36 kb
#include <bits/stdc++.h>

using namespace std;

const int v_max = 2e2;
const int vmax = 2e2 + 10;
const int gmax = 75e3 + 10;

const int inf = 2e4 + 10;

int n, g;
int nr[vmax];
int dp[2][gmax], w_left[2][gmax];

vector < int > ans;
deque < int > dq;

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

int get_dp(int p, int i, int val) {
    int k = (i - p) / val;
    return dp[0][i-k*val];
}

void update_ans(int i, int val, int p, int mid) {
    int k = (i - p) / val;

    dp[1][i] = inf;
    if (dp[0][i-k*val] == inf) return;

    dp[1][i] = dp[0][i-k*val] + k;
    w_left[1][i] = (val <= mid) ? i : w_left[0][i-k*val];
}

void compute_dp(int left, int right, int g) {
    int mid = (left + right) >> 1;

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

    for (int val = left; val <= right; ++val) { //gap = val
        if (nr[val] == 0)
            continue;

        for (int r = 0; r < val; ++r) {
            dq.clear();
            for (int i = r; i <= g; i += val) {
                if ((int)dq.size() && (i - dq.front()) / val == nr[val] + 1)
                    dq.pop_front();
                while ((int)dq.size() && dp[0][i] <= get_dp(dq.back(), i, val))
                    dq.pop_back();
                dq.push_back(i);

                if ((int)dq.size())
                    update_ans(i, val, dq.front(), mid);
            }
        }

        memcpy(dp[0], dp[1], (g + 1) << 2);
        memcpy(w_left[0], w_left[1], (g + 1) << 2);
    }
}

void compute_sol(int left, int right, int g_act) {
    if (g_act == 0) return;
    if (left == right) {
        for (int i = 1; i <= g_act / left; ++i)
            printf("%d\n", left);
        return;
    }

    compute_dp(left, right, g_act);

    int mid = (left + right) >> 1;
    int w_act; for (w_act = g_act; dp[1][w_act] == inf; w_act--);

    if (right - left == v_max - 1)
        printf("%d %d\n", w_act, dp[1][w_act]);

    int w_leftACT = w_left[1][w_act];
    compute_sol(left, mid, w_leftACT);
    compute_sol(mid + 1, right, w_act - w_leftACT);
}

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

    input();
    compute_sol(1, v_max, g);

    return 0;
}