Cod sursa(job #3335987)

Utilizator Nasa1004Ema Nicole Gheorghe Nasa1004 Data 23 ianuarie 2026 22:34:14
Problema Ghiozdan Scor 76
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.89 kb
#pragma GCC optimize ("Ofast", "unroll-loops")
#include <fstream>
#include <vector>
#include <queue>

using namespace std;
const int NMAX = 200;
const int GMAX = 75000;
const int INF = 21000;

ifstream cin("ghiozdan.in");
ofstream cout("ghiozdan.out");

int cnt[NMAX + 2];
vector <pair <int, int>> cat; ///val, index

vector <int> build(int st, int dr, int g) {
    vector <int> dp[2]; ///pastram doar ultimele 2 randuri
    dp[0].assign(g + 1, INF);
    dp[1].assign(g + 1, INF);
    dp[0][0] = 0, dp[1][0] = 0;

    for(int i = 0; i <= dr - st; i++) {
        int id = st + i;
        int k = cnt[id];
        for(int rest = 0; rest < id; rest++) {
            deque <int> dq;
            for(int j = 0; j * id + rest <= g; j++) {
                int nr = j * id + rest;
                while(!dq.empty() && dp[0][dq.back() * id + rest] - dq.back() > dp[0][nr] - j)
                    dq.pop_back();
                dq.push_back(j);
                while(!dq.empty() && dq.front() + k < j)
                    dq.pop_front();

                dp[1][nr] = dp[0][dq.front() * id + rest] + (j - dq.front());
            }
        }
        /*if(i <= 5) {
            for(int j = 0; j <= g; j++)
                cout << dp[1][j] << " ";
            cout << '\n';
        }*/
        dp[0] = dp[1];
        dp[1].assign(g + 1, INF);
        ///dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - x] + 1, dp[i - 2][j - 2 * x] + 2, ... dp[i - ][j - k * x]
    }
    return dp[0];
}

void solve(int g, int minn, int st, int dr) { ///g = suma, minn = nrelem
    if(minn == 0 || g == 0)
        return;
    // cout << "Solve " << g << " cu nr mutari " << minn << " in interv -> " << st << " " << dr << '\n';
    if(st == dr) { ///un singur elem
        cat.push_back({st, minn}); ///toate cate au ramas
        return;
    }
    int mid = (st + dr) / 2; ///ce facem
    vector <int> l = build(st, mid, g);
    vector <int> r = build(mid + 1, dr, g);

    for(int i = 0; i <= g; i++) {
        if(l[i] + r[g - i] == minn) { ///fix cat cautam
            // cout << "st " << i << " cu " << l[i] << '\n';
            // cout << "dr " << g - i << " cu " << r[g - i] << '\n';
            solve(i, l[i], st, mid);
            solve(g - i, r[g - i], mid + 1, dr);
        }
    }
}

int main() {
    int n, g, minLim = 200, maxLim = 1;
    cin >> n >> g;
    for(int i = 1; i <= n; i++) {
        int a;
        cin >> a;
        cnt[a]++;
        minLim = min(minLim, a);
        maxLim = max(maxLim, a);
    }
    vector <int> ans = build(minLim, maxLim, g);
    int gmax = 0, minn = 0;
    for(int i = g; i >= 0; i--) {
        if(ans[i] != INF) {
            gmax = i;
            minn = ans[i];
            break;
        }
    }
    solve(gmax, minn, minLim, maxLim);
    cout << gmax << " " << minn << '\n';
    for(auto& x : cat) {
        while(x.second) {
            cout << x.first << '\n';
            x.second--;
        }
    }
    return 0;
}
/*
5 9
2 2 2 2 4
*/