[BZOJ2456] mode - 贪心

2456: mode

Time Limit: 1 Sec   Memory Limit: 1 MB
Submit: 2890   Solved: 1223
[ Submit][ Status][ Discuss]

Description

给你一个n个数的数列,其中某个数出现了超过n div 2次即众数,请你找出那个数。

Input

第1行一个正整数n。
第2行n个正整数用空格隔开。

Output

    一行一个正整数表示那个众数。

Sample Input

5
3 2 3 1 3

Sample Output

3

HINT

100%的数据,n<=500000,数列中每个数<=maxlongint。



zju2132 The Most Frequent Number

Source

鸣谢 黄祎程


啊这真是个神奇的东西。。。

不严密而不严谨的题解:

根据题目的规定,出现最多的数出现次数一定是总数的一半以上。在这里我用tmp记录当前的答案,用t来表示当前答案从记录的地方开始比不是这个答案的多的个数

这样说可能比较难懂。但是下面我们来模拟一组数据:

8

2 3 3 2 3 3 2 3

首先我们读入样例的总数n=8,然后读入第一个数据2.下面我们暂且把2号妹子当做答案。那么现在我们就相当于从第一个数开始选择到第一个数,现在这些数中和所选的数相同的(即2)有一个,不同的有0个,我们就把t赋值为1。

接下来,我们读入第二个数3,这时不同的数的个数就为1了,于是我们将t自减,变为0。

再然后,我们读入第三个数3,不同数的个数变为2,再自减t,变为-1。这时,我们就决定不选择该数,而选择我们读入的数3记为tmp,将t清空重新计算。

之后一直这样计算,就能得到最后的答案。

 

不严谨而不严密的证明:即证明对于一组数其中的一个数,总有从其中的一个数字相同的点出发会在后面的判断中始终不改变tmp,且第一个tmp一定是最终的答案。

 ∵这个数的出现次数大于总次数的一半

 我们假设这个最终的答案出现在一个位置。并且在之后会因为不同的妹子太多被覆盖。

 那么,不同的数的个数一定大于这个最终的答案数。

 ∴在下一次这个数出现时,这个数的剩余总个数一定仍然超过剩余数的总个数的一半。

 ∴以此类推,最终能够得到答案

#include "stdio.h"
using namespace std;
inline void read(int & v){
char ch;int poi=1;while(ch=getchar(),ch!='-'&&(ch>'9'||ch<'0'));
if(ch=='-')poi=-1,ch=getchar();v=0;
while(ch<='9'&&ch>='0')v=v*10+ch-'0',ch=getchar();
v*=poi;}
main(){int n,i,tmp,t=1,q;read(n),read(tmp);
for(i=2;i<=n;i++){read(q);if(q==tmp)++t;else --t;if(t<0)tmp=q,t=1;}
printf("%d",tmp);}

唔……有压代码长度……

你可能感兴趣的:([BZOJ2456] mode - 贪心)