Pagini recente » Cod sursa (job #3352835) | Cod sursa (job #2089261) | Borderou de evaluare (job #1514750) | Cod sursa (job #2889032) | Cod sursa (job #3335987)
#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
*/