Cod sursa(job #19344)

Utilizator bogdan2412Bogdan-Cristian Tataroiu bogdan2412 Data 19 februarie 2007 12:35:48
Problema Ghiozdan Scor 80
Compilator c Status done
Runda Arhiva de probleme Marime 1.76 kb
#include <stdio.h>
#include <assert.h>
#include <string.h>

#define MAX 200
#define MAXG 75005

int N, G;
short c[MAX + 1];

int best[2][MAXG];
short up[2][MAXG];

int d[MAXG], p[MAXG], dl, dr;

inline void initdeque() { dl = 0; dr = -1; }

inline void adddeque(int val, int poz, int L)
{
	while ( dr >= dl && d[dr] + poz - p[dr] >= val ) dr--;
	d[++dr] = val;
	p[dr] = poz;
	if (poz - p[dl] > L)
		dl++;
}

int solve( int l1, int c1, int l2, int c2 )
{
	assert( l1 <= l2 && c1 <= c2 );
	if (l1 > l2 || c1 > c2)
		return 0;

	if (l1 == l2)
	{
		assert( c[l1] >= (c2 - c1) / l1 );
		int k = (c2 - c1) / l1;
		for (; k; k--)
			printf("%d\n", l1);
		return 0;
	}

	int m = (l1 + l2) >> 1, i, step = 1;
	memset( best[0], 0x3f, sizeof( best[0] ) );
	best[0][c1] = 0;

	for (i = l1; i <= l2; i++, step ^= 1)
	{
		int j, r;
		//nxt[i] = max( prv[i - x * cur] + x | x <= c[cur] && x <= i / cur )
		//nxt -> best[step]; prv -> best[1 ^ step]; cur -> i
		//deque for every different remainder
		for (r = 0; r < i; r++)
		{
			initdeque();
			for (j = c1 + r; j <= c2; j += i)
			{
				adddeque( best[1 ^ step][j], j / i, c[i] );
				best[step][j] = d[dl] + j / i - p[dl];
				int np = ( j - ((j / i - p[dl]) * i) );
				up[step][j] = (i <= m) ? j : up[1 ^ step][np];
			}
		}
	}
	int last = c2, UP, bst;
	for (; best[1 ^ step][last] == 0x3f3f3f3f && last >= c1; last--);
	bst = best[1 ^ step][last];

	if (l1 == 1 && l2 == MAX)
		printf("%d %d\n", last, best[1 ^ step][last]);

	UP = up[1 ^ step][last];
	assert(solve( l1, c1, m, UP ) +	solve( m + 1, UP, l2, last ) >= 0);

	return bst;
}

int main()
{
	freopen("ghiozdan.in", "rt", stdin);
	freopen("ghiozdan.out", "wt", stdout);

	int i, j;
	for (scanf("%d %d", &N, &G), i = 0; i < N; i++)
	{
		scanf("%d", &j);
		c[j]++;
	}

	solve(1, 0, MAX, G);

	return 0;
}