题目链接:http://codeforces.com/contest/1163/problem/B2
题意:有 n n n个数,你要选前 k k k个数,要求前 k k k个数中删掉一个数之后剩下的相同数字的个数相同。
解题心得:从前往后遍历记录以下数据:当前数的个数
m
a
p
i
map_{i}
mapi,相同的个数
c
n
t
i
cnt_{i}
cnti,个数的种类
s
e
se
se。
当
s
e
=
=
2
se == 2
se==2的时候:个数少的那个数
c
n
t
=
=
1
cnt==1
cnt==1,并且
m
a
p
=
=
1
map==1
map==1,可以直接删掉这个数,当前符合条件。当两个不同种类的个数的相同个数差值为1,并且多的那个种类数的个数为1的时候直接减去。
当
s
e
=
=
1
se==1
se==1的时候特判一些条件就好了。
说起来十分绕,看不懂没关系,就是一个脑筋急转弯想想就能够想明白的。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+100;
map <int, int> maps;
int n, cnt[maxn];
set <int> se;
int main() {
//freopen("1.in", "r", stdin);
scanf("%d", &n);
int ans = 1, tot = 0;
for(int i=1;i<=n;i++) {
int temp; scanf("%d",&temp);
maps[temp]++;
if(maps[temp] == 1) tot++;
if(cnt[maps[temp]] == 0)
se.insert(maps[temp]);
cnt[maps[temp]]++;
if(cnt[maps[temp]-1] == 1)
se.erase(maps[temp]-1);
cnt[maps[temp]-1]--;
if (se.size() == 2) {
if (*se.begin() == 1 && cnt[1] == 1) ans = i;
else if(abs(*se.begin() - *se.rbegin()) == 1 && cnt[*se.rbegin()] == 1) ans = i;
}
if(se.size() == 1 && maps[temp] == i) ans = i;
else if(se.size() == 1 && tot == i) ans = i;
}
printf("%d\n", ans);
return 0;
}