Cod sursa(job #253837)

Utilizator gabitzish1Gabriel Bitis gabitzish1 Data 6 februarie 2009 12:47:59
Problema Caramizi Scor 10
Compilator cpp Status done
Runda Stelele Informaticii 2009, clasele 9-10, ziua 1 Marime 1.95 kb
#include <cstdio>

#define MAXN 200005

int N, M, sum, X, min, K;
int v[MAXN], h[MAXN], a[MAXN], h2[MAXN];
long long val[MAXN];

void swap(int &x, int &y)
{
	int aux = x; x = y; y = aux;
}

void urc(int k)
{
	if (k <= 1) return;
	if (v[ h[k] ] > v[ h[k / 2] ])
	{
		swap(h[k], h[k / 2]);
		urc(k / 2);
	}
}

void cobor(int k)
{
	int max, st, dr;

	max = k;
	st = 2 * k; dr = st + 1;

	if (st <= K && v[ h[st] ] > v[ h[max] ]) max = st;
	if (dr <= K && v[ h[dr] ] > v[ h[max] ]) max = dr;

	if (max != k)
	{
		swap(h[max], h[k]);
		cobor(max);
	}
}

int caut(int x)
{
	int p, u, m, sol;
	sol = N;
	p = 1; u = N;
	while (p <= u)
	{
		m = (p + u) / 2;
		if (val[m] <= x)
		{
			sol = m;
			u = m - 1;
		}
		else p = m + 1;
	}
	return sol;
}

void calcul(int x)
{
	int i, cnt = 0;
	for (i = 1; i <= N; i++) v[i] = a[i], h[i] = h2[i];
	K = N;

	while (K >= x)
	{
		for (i = 1; i <= x; i++)
		{
			v[ h[1] ]--;
			swap(h[1], h[K]);		
			K--;
			cobor(1);
		}
		K = 0;
		for (i = 1; i <= N; i++) 
		{
			if (v[i] > 0) 
			{
				K++;
				urc(i);
			}
		}	
		cnt++;
	}
	val[x] = cnt;
}	

long long minim(long long x, long long y) { return x < y ? x : y;}
long long max(long long x, long long y) { return x > y ? x : y;}


int main()
{
	freopen("caramizi.in","r",stdin);
	freopen("caramizi.out","w",stdout);

	int i, j;
	scanf("%d %d", &N, &M);
	min = (1<<30);

	for (i = 1; i <= N; i++)
	{
		scanf("%d ", &v[i]);
		sum += v[i];
		min = (min > v[i] ? v[i] : min);

		h[++K] = i;
		urc(K);
	}

	for (i = 1; i <= N; i++) a[i] = v[i], h2[i] = h[i];

	val[N] = min;
	val[1] = sum;

	for (i = N - 1; i > 1; i--)	calcul(i);

	long long rez;

	for (i = 1; i <= M; i++)
	{
		scanf("%d",&X);
		j = caut(X);
		rez = (long long)j * (minim(X, val[j]));		
		while (val[j] < X) 
		{
			j--;
			rez = max(rez, (long long)j * minim(X, val[j]));
		}
		
		printf("%lld\n", rez);
	}
	return 0;
}