题意:给出n个选手的成绩,要给他们按成绩高低颁发金银铜牌,所有奖牌数不得多于参赛者人数的一半,同时金银铜牌都必须颁发,金牌数要小于银牌数和铜牌数,现在要尽可能把奖牌发完,问最佳的金银铜牌颁发方案。
思路:很显然贪心,因为题并没有说银牌和铜牌的关系,那么我们就固定金牌数(比如只给最高分的人金牌,好惨。。。),然后给成绩靠后的人发尽可能多的银牌和铜牌。不过话说这题用1e6的num数组就超时。。。
#include <bits/stdc++.h>
using namespace std;
const int Maxn=1e6+10;
const int maxn=4e5+1;
typedef long long ll;
int T,n;
ll a[maxn],num[maxn],b[maxn];
inline long long read() {
long long tmp=0, fh=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') fh=-1; c=getchar();}
while (c>='0'&&c<='9') tmp=tmp*10+c-48, c=getchar();
return tmp*fh;
}
int main()
{
scanf("%d",&T);
while(T--)
{
map<int,int>num;
scanf("%d",&n);
int tot=n>>1,size=0;
for(int i=1;i<=n;++i)
{
b[i]=read();
num[b[i]]++;
}
if(n<10) {
printf("0 0 0\n");
continue;
}
b[0]=Maxn;
for(int i=1;i<=n;++i)
{
if(b[i]!=b[i-1]) a[++size]=b[i];
}
ll g=num[a[1]],s=0,t=0;
int k=2;
while(s<=g&&k<=size)
{
s+=num[a[k]];
k++;
}
while(g+s+t<=tot&&k<=size)
{
t+=num[a[k]];
k++;
}
k--;
t-=num[a[k]];
if(g+s+t>tot||g>=s||g>=t){
printf("0 0 0\n");
continue;
}
printf("%lld %lld %lld\n",g,s,t);
}
}