Pagini recente » Cod sursa (job #832816) | Cod sursa (job #3336897) | Cod sursa (job #3350765) | Cod sursa (job #2298049) | Cod sursa (job #3335569)
#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;
}