Cod sursa(job #1905428)

Utilizator RazvanR104Razvan-Andrei Ciocoiu RazvanR104 Data 6 martie 2017 02:49:09
Problema Ghiozdan Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 1.61 kb
#include <bits/stdc++.h>

using namespace std;

const int GMAX = 75010, WMAX = 210;
const int inf = 0x3f3f3f3f;

int N, G;
int weight[WMAX];
int DP[2][GMAX], from[2][GMAX];

void solveDP(int left, int right, int w) {
	int i, j, r;
	if (w == 0)
		return;
	if (left == right) {
		for (i = 1; i * left <= w; ++i)
			cout << left << '\n';
		return;
	}
	int mid = (left + right) / 2;
	int curr = 0, prev = 1;
	memset(DP[0], inf, sizeof DP[0]);
	DP[0][0] = 0;
	for (i = left; i <= right; ++i) {
		swap(curr, prev);
		for (r = 0; r < i; ++r) {
			deque<pair<int, int>> minD;
			int add = 0;
			for (j = 0; i * j + r <= w; ++j) {
				if (minD.size() && minD.front().first < j - weight[i])
					minD.pop_front();
				while (minD.size() && minD.back().second >= DP[prev][i * j + r] - add - 1)
					minD.pop_back();
				minD.push_back({j, DP[prev][i * j + r] - add - 1});
				++add;
				DP[curr][i * j + r] = minD.front().second + add;
				from[curr][i * j + r] = (i <= mid ? i * j + r : from[prev][i * minD.front().first + r]);
			}
		}
	}
	int maxWeight = w;
	while (DP[curr][maxWeight] >= inf)
		--maxWeight;
	if (left == 1 && right == 200)
		cout << maxWeight << ' ' << DP[curr][maxWeight] << '\n';
	int midWeight = from[curr][maxWeight];
	solveDP(left, mid, midWeight);
	solveDP(mid + 1, right, maxWeight - midWeight);
}

int main() {
	assert(freopen("ghiozdan.in", "r", stdin));
	assert(freopen("ghiozdan.out", "w", stdout));
	int i;
	scanf("%d %d", &N, &G);
	for (i = 1; i <= N; ++i) {
		int currWeight;
		scanf("%d", &currWeight);
		++weight[currWeight];
	}
	solveDP(1, 200, G);
	return 0;
}