原文题目
You are given an array of integers. Vasya can permute (change order) its integers. He wants to do it so that as many as possible integers will become on a place where a smaller integer used to stand. Help Vasya find the maximal number of such integers.
For instance, if we are given an array [10,20,30,40], we can permute it so that it becomes [20,40,10,30]. Then on the first and the second positions the integers became larger (20>10, 40>20) and did not on the third and the fourth, so for this permutation, the number that Vasya wants to maximize equals 2. Read the note for the first example, there is one more demonstrative test case.
Help Vasya to permute integers in such way that the number of positions in a new array, where integers are greater than in the original one, is maximal.
Input
The first line contains a single integer n (1≤n≤105) — the length of the array.
The second line contains n integers a1,a2,…,an (1≤ai≤109) — the elements of the array.
Output
Print a single integer — the maximal number of the array’s elements which after a permutation will stand on the position where a smaller element stood in the initial array.
中文题意
给了一个数组,要求将数组重新排列后,有多少个位置上的新的数字大于旧的数字
题解
题目要求的是大于原来的数的数目,那么本质上就是找一个数大于原来的数,问能找到多少个。
因为一个数在被找到之后就不能用了,所以我们可以很容易想到极限情况,就是刚刚好比这个数大,也就是离这个数最近的大于它的数。
因为是找,如果是传统的O(n^2)暴力枚举一定会超时,所以为了降低时间成本,我们可以采用二分查找:
如果当前的数比原来的数大,而且当前的数没有被使用过,那么就记录当前的数,然后向左找(为了找到刚刚好大于它的数)
否则就向右找
注意,每一次找到一个符合条件的mid后都要保存下来,因为我们要取的是最优情况的mid,也就是每次如果能找到,就只标记最优的,对于剩下的我们可以用给别的数。
但是,我们也要给原来的数组排序,这样如果找到的mid是用过的,那么就直接向右找就可以了,这是类似贪心的思想,如果这个数被用了,说明它满足了一个恰好的最大值,那么小于它的数一定也满足被用了,或者就并不适用,所以我们需要向右找就可了
#include <bits/stdc++.h>
using namespace std;
int a[100005];
int b[100005];
int c[100005];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n,i,j,k,t,s;
cin>>n;
for(i=0;i<n;i++){
cin>>a[i];
b[i]=a[i];
}
int mid;
sort(a,a+n);
sort(b,b+n);
t=0;
bool flag;
j=-1;
for(i=0;i<n;i++){
flag=0;
s=b[i];
int l=0;
int r=n-1;
while(l<=r){
mid=l+(r-l)/2;
if(a[mid]>s&&c[mid]==0){
j=mid;
flag=1;
r=mid-1;
}
else l=mid+1;
}
if(flag==1)
{
t++;
c[j]=1;
//cout<<j<<" "<<i<<endl;
}
}
cout<<t<<endl;
}