【中山市选2011】新年礼物

Description

  Windbreaker计划送一些项链给他的朋友们作为新年礼物。为了表示诚意,他决定自己制作全部的项链。他购买了若干种珍珠,每种珍珠都有特定的颜色。他要制作的项链都是M-完美的,也就是每条项链都是恰好由M种珍珠组成的。Windbreaker想知道他最多能送出多少条项链。给定每种珍珠的数目,你要回答的是Windbreaker最多可以制作多少条M-完美项链。

Input

  输入包含多组测试数据。每组数据第一行是一个正整数n,代表有n种珍珠。第二行包含n个正整数,代表每种珍珠的数目。第三行包括1个正整数M,代表要制作的是M-完美项链。   输入数据以1行n=0结束。这组数据不用处理。

Output

  对每组测试数据,输出一行答案,为一个整数,代表最多能制作的M-完美项链的数目。

Sample Input

5 3 3 3 3 3 5 6 1 2 3 4 5 6 5 0

Sample Output

3 3

Data Constraint

对20%的数据,有n<=10;

对40%的数据,有n<=100;

对100%的数据,有n<=1000,每种珍珠数目不超过2000,1<=M<=100。

Source / Author: gift

显然从大的开始贪心,把前m大的几个凑一组,都减1.

不用每次排序,堆就好了。

#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define N 2010
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
#define INF 2147483647
using namespace std;


int n,m,i,j,k,t,ans,p1,p2,cnt,len;
int f[N],a[N],G[N],h[N*10];

void up(int x)
{
	if(x < 2)return ;
	if(h[x/2] < h[x])swap(h[x],h[x/2]),up(x/2);
}

void down(int x)
{
	if(x * 2  > len)return ;
	int flag1=1,flag2=1;
	if(h[x] > h[x*2]) flag1 =0 ;
	if(x*2+1 > len || h[x] > h[x*2+1]) flag2=0;
	if(!flag1 && !flag2)return ;
	if(flag1 && flag2)
	{
		if(h[x*2] > h[x*2+1])swap(h[x] , h[x*2]),down(x*2);
			else swap(h[x] , h[x*2+1]),down(x*2+1);
	}else
	if(flag1)
		swap(h[x] , h[x*2]),down(x*2);
		else
		swap(h[x] , h[x*2+1]),down(x*2+1);
	//flag2
}

void hp_delete()
{
	h[1] = h[len--];
	down(1);
}

void hp_insert(int x)
{
	h[++len] = x;
	up(len);
}

int main()
{
	while(scanf("%d",&n),n)
	{
		len=0;
		mem(h,0);
		for(i=1;i<=n;i++)scanf("%d",&a[i]),hp_insert(a[i]);
		scanf("%d",&m);
		
		ans =0;
		
		while(len >= m)
		{
			int minn = 1;
			for(i=1;i<=m;i++)
				G[i] = h[1] , hp_delete() , minn = min(minn , G[i]);
			for(i=1;i<=m;i++)G[i] -= minn;
			for(i=1;i<=m;i++)if(G[i])hp_insert(G[i]);
			ans+=minn;
		}
		
	
		printf("%d\n",ans);
	}
	return 0;
}

O(sigma(a[i]) log n )

猜你喜欢

转载自blog.csdn.net/Com_man_der/article/details/89458689