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 )