原题链接:https://codeforces.com/contest/1265/problem/C
题目内容
实例
input
5
12
5 4 4 3 2 2 1 1 1 1 1 1
4
4 3 2 1
1
1000000
20
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
32
64 64 63 58 58 58 58 58 37 37 37 37 34 34 28 28 28 28 28 28 24 24 19 17 17 17 17 16 16 16 16 11
output
1 2 3
0 0 0
0 0 0
2 5 3
2 6 6
解题思路
因为题目中数组要求从大到小排序好了,所以只需考虑以下问题:
1、先从数组中第一个数据开始,计算金牌的数目nug。
2、再从第nug+1数据开始,计算银牌的数目nus。长度为n的数组a,把a[n/2+1]的值记录下来,为as,如果出现a[i]==a[as](i<=n/2),终止计数。
3、最后,从nug+nus+1开始,计算铜牌的数目nud:长度为n的数组a,把a[n/2+1]的值记录下来,为as,如果出现a[i]==a[as](i<=n/2),终止计数。
最后,也是最最重要的,如果nug 、 nus 、 nud 中任何一个为零,或者nug大于等于后两者的任何一个,都输出0 0 0。
正确代码
#include <iostream>
#include<cstring>
#include<algorithm>
#include<stdio.h>
#include<cstdio>
#include<string>
using namespace std;
typedef long long ll;
const int maxn=4*1e5+7;
int a[maxn];
int main()
{
int t;
cin>>t;
for(ll x=1;x<=t;x++){
memset(a,0,sizeof(a));
ll n;
cin>>n;
ll as=0;
for(ll i=1;i<=n;i++){
cin>>a[i];
if(i==((n/2)+1))
as=a[i];
}
ll gsd,nug=1;
gsd=n/2;
for(ll i=2;i<=gsd;i++){
if(a[i]==a[i-1])
{
nug++;//金牌数
}
else
break;
}
ll nus=0;
for(ll i=nug+1;i<=gsd;i++){
if(a[i]==as) break;
else if(a[i]==a[i-1]||(i-nug-1)<=nug)
{
nus++;//银牌数
}
else
break;
}
int nud=0;
for(ll i=nus+nug+1;i<=gsd;i++){
if(a[i]==as)
break;
else
nud++;//铜牌数
}
if(nug==0||nus==0||nud==0||nug>=nus||nug>=nud)
cout<<0<<" "<<0<<" "<<0<<endl;
else
cout<<nug<<" "<<nus<<" "<<nud<<endl;
}
return 0;
}