原题连接:http://codeforces.com/contest/1008/problem/C
题意:给出n个数,要求重新将这些数排列,求出新排列的数列对应位置比初始数列大的数的个数。
题解:一种方法是贪心,sort一遍,然后对于每个数 a[i] ,用一个pos指针从前往后扫,每扫到连续的小于 a[i] 的数答案就加一。
不过时间复杂度有点高。
另一种方法就是根据样例猜规律(后面会给出证明)。
看到样例
7
10 1 1 1 5 5 3 输出 :4
5
1 1 1 1 1 输出: 0
想到可能答案就是 n - 最多相同的数的个数。
证明:(可能有点难理解,看不懂就算了,会第一种就好了) 假设最多相同的数(记为a)的个数 为 X,那么其他所有数个数总和为 n-X; 那么排序后的数列可以形象地表示为 A X B (A表示小于a的数的个数,B表示大于a的数的个数)。
所有的X中,一部分X可以和A匹配,剩余的X肯定都比B小,所以所有的B都可以和X匹配,因此答案就是A+B,其实就是 n-X;
比如样例
7
1 4 4 4 5 3 5
排序后:1 3 4 4 4 5 5,那么X = 3,A = 2,B = 2;
一部分X与A匹配
1 3 4 4 4 5 5
4 4
然后把所有B移到匹配后的数后面,剩下的位置随便排
1 3 4 4 4 5 5
4 4 5 5 4 1 3
答案就是 4
可以自己再举几个例子试试
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
ll a[maxn];
map<ll,ll>mp;
int main(){
int n;
scanf("%d",&n);
mp.clear();
ll ans = 0;
for(int i = 1; i <= n; i++){
scanf("%lld",&a[i]);
mp[a[i]]++; //map记录相同的数的个数
ans = max(ans,mp[a[i]]); //更新最大个数
}
printf("%d\n",n-ans);
}