1705: 完美数组(New Online Judge)
题目描述
完美数组的定义如下:
1、完美数组长度为偶数(包括0)
2、从左往右每两个数字都必须是一样的,即A、A、B、B、C、C…
例如:2 2 4 4 6 6 7 7是一个长度为8的完美数组。
现在,给你两个长度为n的数组,恰好每个数字出现2次,你可以删去一些数字,使得这两个数组变成完美数组。
删去数字时,无法改变其他数字的相对位置。
删去数字的代价为删去数字中的最大值。例如1 2 2 3 4 4删去数字1和3变成2 2 4 4,代价为3。
请问将这两个数组变成完美数组的最小代价是多少?
输入
输入第一行包含一个正整数n( 1 ≤ n ≤ 1 0 6 1≤n≤10^6 1≤n≤106)。
接下来两行每行n个数字,分别表示给定的两个数组。
输出
输出一个数字,表示最小代价。
样例输入
样例1:
5
2 1 3 3 2
6 6 7 1 7
样例2:
6
1 1 2 2 3 3
4 4 5 5 6 6
样例输出
样例1:
2
样例2:
0
题解1(C++版本)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, a[N], ans;
bool check(int x){
int last = -1;
for(int i = 1; i <= n; i++){ //将所有<=x的元素都忽略掉
if(a[i] > x){
if(last == -1) last = a[i];
else if(last != a[i]) return false;
else if(last == a[i]) last = -1;
}
}
return last == -1 ?true : false; //最后一个值只有奇数个
}
int main(){
scanf("%d", &n);
for(int k = 1; k <= 2; k++){
memset(a, 0, sizeof a);
int l = -1, r = 0, mid;
for(int i = 1; i <= n; i++) scanf("%d", &a[i]), r = max(r, a[i]);
r++;
//l = -1, r= max(a[1],a[2],...,a[n])+1
// 左边界的确定:不需要删除数组元素,此时代价为0
// 右边界的确定:删除数组中的所有元素,此时代价为max(a[1],a[2],...,a[n])
// 这里取开区间,方便处理边界
while(l + 1 < r){ //二分答案
mid = (l + r)/2;
if(check(mid)) r = mid; //r最后一定指向这组数据的答案所在的位置
else l = mid;
}
ans = max(ans, r);
}
printf("%d\n", ans);
return 0;
}