http://codeforces.com/contest/1008/problem/C
解题思路:
1.给出一个序列,你可以任意变换数字的位置,最终使得所有位置比原位置的数大于的总和最大
2.先对数组进行小到大排序
3.计算所有相同值的个数
4.最左边的一组数都能被它右边的任意值覆盖而达到要求,当然这个覆盖的数量是最左边组和次左边组的个数的较小值
5.然后用这两组合并成为新的一组可以被覆盖的序列,选择两组的较大值,因为覆盖过后的和 未覆盖的或者未被覆盖的 都可以被它们右边下一组的值覆盖
6.重复4,5操作,最后退出循环后再进行一次计算覆盖数量即可
7.注意出现序列全部的值都相同的情况
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] w = new int[100010];
for(int i = 0;i < n;i++) {
w[i] = sc.nextInt();
}
Arrays.sort(w,0,n);
long ans = 0,sum = 1;
int i;
for(i = 1;i < n;i++) { //记录最小值的个数
if(w[i] == w[i - 1])
sum++;
else break;
}
boolean tag = true;
if(i == n) //所有数字都相等,答案就是0
tag = false;
long sum2 = 1;
for(i = i + 1;i < n;i++) {
if(w[i] == w[i - 1]) //计算下一组相同值的个数
sum2++;
else {
ans += Math.min(sum,sum2); //总数加上两组个数的较小值
sum = Math.max(sum,sum2); //维护当前可以被覆盖的数量
sum2 = 1; //重新计算
}
}
if(tag == true)
ans += Math.min(sum,sum2);
System.out.println(ans);
}
}