Cod sursa(job #572174)

Utilizator pestePopescu A peste Data 5 aprilie 2011 08:42:16
Problema Stalpi Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.5 kb
//by Puni Andrei-Paul
//Time complexity: O(N*D*log D)
//Space complexity: O(N*D)
//Method: DP + deque
//Working time: 45 minutes

#include <cstdio>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <vector>

using namespace std;

#define Nmax 51
#define Emax 400000
#define Dmax 10001
#define Inf best[0][0]

int N,E, d[Nmax];

int best[Nmax][Dmax];

int dq[Dmax], st, dr;


bool se_poate(int D)
{
	memset(best, 0x3f, sizeof best);
	
	//si in rest infinit ... pt ca nu pot sa il misc pe 1 ..
	best[1][0] = 0;
	
	for (int i = 2; i <= N; ++i)
	{
		//init dq		
		st = 1;	dr = 0;
		
		for (int j = 0; j <= d[N]; ++j)
		{	
			//le scoti pe alea de care nu ai nevoie			
			while (st <= dr && abs(j - dq[st]) > D)
				++st;
			
			//le scoti pe alea care nus destul de bune
			while (st <= dr && best[i-1][dq[dr]] >= best[i-1][j])
				--dr;
				
			//bagi aia noua
			dq[++dr] = j;						
			
			best[i][j] = abs(d[i]-j) + best[i-1][dq[st]];	
			if (best[i][j] > Inf) 
				best[i][j] = Inf;
		}
	}
	
	return (best[N][d[N]] <= E);	
}

int main()
{
	assert(freopen("stalpi.in", "r", stdin) != NULL);
	assert(freopen("stalpi.out", "w", stdout) != NULL);
	
	assert(scanf("%d%d", &N, &E) == 2);
	assert(3 <= N && N < Nmax);
	assert(1 <= E && E <= Emax);
	
	for (int i = 2; i <= N; ++i)
	{
		assert(scanf("%d", &d[i]) == 1);
		assert(d[i-1] <= d[i] && d[i] < Dmax);							
	}	
	
	int ret = d[N];
	
	for (int i = 1<<20; i > 0; i /= 2)
	if (ret - i >= 0)
	if (se_poate(ret - i))
		ret -= i;
		
	printf("%d\n", ret); 
	
	return 0;	
}