Cod sursa(job #3335569)

Utilizator iulia_morariuIuli Morariu iulia_morariu Data 22 ianuarie 2026 22:33:58
Problema Ghiozdan Scor 36
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.84 kb
#include <algorithm>
#include <iostream>
#include <fstream>
#include <climits>
#include <vector>
#include <queue>
#include <cmath>
// #include <bits/stdc++.h>
#define in  fin
#define out fout

using namespace std;
using ll = long long;
const int GMAX = 75005, NMAX = 20000;

ifstream fin("ghiozdan.in");
ofstream fout("ghiozdan.out");

int n, g;
int dp[GMAX][2];
int ult[GMAX][2]; // l-as fi numit r da coincide cu ala din divide
int v[NMAX];
int vf[201]; // minimude201 reference
ll dp1[GMAX];
// ll ult[GMAX], ult_nr[GMAX];

void imparte_si_cucereste(int l, int r, int g_acuma){ // care e modul bun sa fac pe L - R costul g_acuma?
    if(l == r){ // cred ca am lowkey terminat
        int cnt = g_acuma / l; // ca gen de atatea ori il pun
        if(cnt > vf[l]) out << "oh no\n"; // nush ce sa fac daca se intampla asta deci osa sper ca nu se intampla
        for(int i = 0; i < cnt; i++) out << l << '\n';
        return;
    }

    // acuma eu idk exact ce vrea sa fie ala cu deque ca uhm
    // mi cam lene sa fac calumea asa ca facem asa

    for(int i = 0; i <= g_acuma; i++){
        dp[i][(l - 1) % 2] = INT_MAX;
        ult[i][(l - 1) % 2] = i;
    }
    int m = (l + r) / 2;
    dp[0][0] = 0;
    // cout << "Sunt la ( " << l << " , " << r << " ) g = " << g_acuma << '\n';
    for(int nr = l; nr <= r; nr++){;
        for(int i = 0; i <= g_acuma; i++){
            dp[i][nr % 2] = dp[i][(nr - 1) % 2];
            ult[i][nr % 2] = ult[i][(nr - 1) % 2];
            if(nr == m + 1) ult[i][nr % 2] = i; // ca aici gen incepe tot
        }
        if(vf[nr] == 0) continue;
        // cout << "  -- > incerc sa gatesc cu " << nr << '\n';
        for(int x = g_acuma; x >= 0; x--){
            // cout << "    -- > gatesc cu x = " << x << '\n';
            for(int k = x - nr; k >= 0 && (x - k) / nr <= vf[nr]; k -= nr){
                if(dp[k][(nr - 1) % 2] == INT_MAX) continue;
                if(dp[x][nr % 2] > dp[k][(nr - 1) % 2] - k / nr + x / nr){
                    // cout << "    -- > fur de la k = " << k << " si am " << dp[k][(nr - 1) % 2] - k / nr + x / nr << '\n';
                    dp[x][nr % 2] = dp[k][(nr - 1) % 2] - k / nr + x / nr;
                    ult[x][nr % 2] = ult[k][(nr - 1) % 2];
                }
            }
        }
    }

    int last = g_acuma;
    while(dp[last][r % 2] == INT_MAX) last--;

    // cout << "Sunt la ( " << l << " , " << r << " ) si pot sa fac " << last << '\n';

    imparte_si_cucereste(l, m, ult[last][r % 2]);
    imparte_si_cucereste(m + 1, r, last - ult[last][r % 2]);
}

signed main(){
    ios_base::sync_with_stdio(false);
    in.tie(NULL);

    in >> n >> g;
    for(int i = 0; i < n; i++){
        in >> v[i];
        vf[ v[i] ]++;
    }

    // initial trebe sa fac dinamica simpla
    // uhhhhhghhhh chiar n-am chef

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

    dp[0][0] = 0;
    for(int nr = 1; nr <= 200; nr++){
        // trebe sa rezolv g-urile cu gen bazat pe resturi
        // cu deque
        // ma rog initial osa fie libidinos si inoptim dar we will deal with that in a moment
        // cout << "sunt la nr = " << nr << '\n';
        for(int i = 0; i <= g; i++) dp[i][nr % 2] = dp[i][(nr - 1) % 2];
        if(vf[nr] == 0) continue;
        for(int x = g; x >= 0; x--){
            // cout << "--> incerc sa fac x = " << x << '\n';
            for(int k = x - nr; k >= 0 && (x - k) / nr <= vf[nr]; k -= nr){
                if(dp[k][nr % 2] == INT_MAX) continue;
                if(dp[x][nr % 2] > dp[k][(nr - 1) % 2] - k / nr + x / nr){
                    dp[x][nr % 2] = dp[k][(nr - 1) % 2] - k / nr + x / nr;
                }
            }
        }
    }

    // cout << "dp : ";
    // for(int i = 0; i <= g; i++) cout << dp[i][0] << " ";
    // cout << '\n';

    int last = g;
    while(dp[last][0] == INT_MAX) last--;
    out << last << " " << dp[last][0] << '\n';
    imparte_si_cucereste(1, 200, last);
    return 0;
}