题目描述
难度分:1400
输入T(≤2×104)表示T组数据。所有数据的n之和≤2×105。
每组数据输入n(2≤n≤2×105)和长为n的数组a(1≤a[i]≤108)。
选择一个整数x(0≤x≤109),生成一个序列b,满足b[i]=|a[i]−x|且b[i]≤b[i+1]。
如果不存在这样的x,输出−1,否则输出任意一个符合要求的x。
输入样例
8
5
5 3 3 3 5
4
5 3 4 5
8
1 2 3 4 5 6 7 8
6
10 5 4 3 2 1
3
3 3 1
3
42 43 42
2
100000000 99999999
6
29613295 52036613 75100585 78027446 81409090 73215
输出样例
4
-1
0
42
2
-1
100000000
40741153
算法
分类讨论
只需要对于任意的i∈[1,n]都满足|a[i]−x|≤|a[i+1]−x|即可。
- 如果a[i]=a[i+1],x随便取什么值都可以。
- 如果a[i]<a[i+1],把绝对值拆开进行分类讨论,可以得到x≤[a[i]+a[i+1]2],其中[.]表示对.向下取整。
- 如果a[i]>a[i+1],把绝对值拆开进行分类讨论,可以得到x≥[a[i]+a[i+1]+12]。
对于每个相邻的数对,维护x左边界l的最大值,以及x右边界r的最小值。如果最后l>r就无解,否则区间[l,r]中任何一个数都可以作为x。
复杂度分析
时间复杂度
只遍历了一遍数组a,时间复杂度为O(n)。
空间复杂度
除开输入的数组a,在整个算法过程中只使用了有限几个变量,额外空间复杂度为O(1)。
C++ 代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 200010;
int t, n, a[N];
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
int r = 1e9, l = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
if(i >= 2) {
if(a[i - 1] < a[i]) {
r = min(r, (a[i - 1] + a[i])/2);
}else if(a[i - 1] > a[i]) {
l = max(l, (a[i - 1] + a[i] + 1)/2);
}
}
}
if(l > r) puts("-1");
else printf("%d\n", r);
}
return 0;
}