为了更好的阅读体检,可以查看我的算法学习网
在线评测链接:P1481
题目描述
导演在组织进行大远会开幕式的排练,其中一个环节是需要参演人员围成一个环形。演出人赞站成了一圈、出于美观度的考虑,导演不希望某一个演员身边的其他人比他低太多或高太多。
现在输出 s s s个参演人员的身高、问在他们站成一圈时,相邻演员的身高差的最大值至少是多少,请你帮忙计算。
输入描述
输入包恬两行,第一行有 1 1 1个正整数,代表人数 n n n。
第二行有个 a a a空格隔开的正整数 h h h,表示第 i i i个演员的身高
数据保证 2 ≤ n ≤ 1 0 5 , 1 ≤ h ≤ 1 0 9 2 \leq n \leq 10^5,1 \leq h \leq 10^9 2≤n≤105,1≤h≤109
输出描述
输出包括一个正整数,表示答案
样例
输入
5
2 1 1 3 2
输出
1
提示
样例输入 2 2 2
2 2 2
10 10 10 20 20 20
样例输入 2 2 2
10 10 10
样例1中排为 1 , 2 , 3 , 2 , 1 1,2,3,2,1 1,2,3,2,1即可。样例 2 2 2中排为 10 , 20 10,20 10,20即可。
1.开幕排练
题目描述
导演在组织进行大远会开幕式的排练,其中一个环节是需要参演人员围成一个环形。演出人赞站成了一圈、出于美观度的考虑,导演不希望某一个演员身边的其他人比他低太多或高太多。
现在输出 s s s个参演人员的身高、问在他们站成一圈时,相邻演员的身高差的最大值至少是多少,请你帮忙计算。
输入描述
输入包恬两行,第一行有
1
1
1个正整数,代表人数
n
n
n。
第二行有个
a
a
a空格隔开的正整数
h
h
h,表示第
i
i
i个演员的身高
数据保证
2
≤
n
≤
1
0
5
,
1
≤
h
≤
1
0
9
2 \leq n \leq 10^5,1 \leq h \leq 10^9
2≤n≤105,1≤h≤109
输出描述
输出包括一个正整数,表示答案
样例
输入
5
2 1 1 3 2
输出
1
样例输入2
2
10 20
样例输入2
10
提示
样例1中排为 1 , 2 , 3 , 2 , 1 1,2,3,2,1 1,2,3,2,1即可。样例 2 2 2中排为 10 , 20 10,20 10,20即可。
解题思路
这一题应该算是今晚最难的题了。
考虑环形这个特殊性质,这里不难想象构造一个对称的序列,相对来说答案是更优的。
观察提示中的序列,那么可以想象到一种构造方法:
即序列排序后,如果n
为奇数,那么先放入一个最大值,若n
为偶数则不做操作。接下来每次往序列的两端插入最大值和次大值(分别插入在左右两边),这样就可以保证序列的对称性。
证明的话,需要考虑一个样例,如2 4 3 9 8 4
,假设直接这样来计算,那么很显然多个波浪(即先递增后递减的区间片段)是不优的。最简单的,我们要构造先递增后递减的序列,并且使得递增序列的长度和递减长度的差值尽可能小(在本题中,两者相等)。
为了代码美观,这里cpp
使用了STL
中的双端队列。
Cpp代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
int n;
cin +/->> n;
vector<int> a(n);
for (int i = 0; i < n; i++)
cin >> a[i];
sort(a.begin(), a.end());
deque<int> d;
for (int i = n - 1; i >= 0; i--)
{
d.push_back(a[i--]);
if (i >= 0)
d.push_front(a[i]);
}
int ans = abs(d.front() - d.back());
int head;
for (int i = 1; i < n; i++)
{
head = d.front();
d.pop_front();
ans = max(ans, abs(head - d.front()));
}
cout << ans << endl;
}
java代码
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scanner.nextInt();
}
Arrays.sort(a);
Deque<Integer> d = new ArrayDeque<>();
for (int i = n - 1; i >= 0; i--) {
d.addLast(a[i--]);
if (i >= 0)
d.addFirst(a[i]);
}
int ans = Math.abs(d.peekFirst() - d.peekLast());
int head;
for (int i = 1; i < n; i++) {
head = d.pollFirst();
ans = Math.max(ans, Math.abs(head - d.peekFirst()));
}
System.out.println(ans);
}
}
python代码
if __name__ == "__main__":
n = int(input())
a = list(map(int, input().split()))
a.sort()
deque = []
for i in range(n - 1, -1, -2):
deque.append(a[i])
if i >= 1:
deque.insert(0, a[i - 1])
ans = abs(deque[0] - deque[-1])
for i in range(1, n):
ans = max(ans, abs(deque[i] - deque[i - 1]))
print(ans)
扩展
这题根据上面的构造,我们可以得到一个结论:答案必然出现在 a b s ( a i − a ( i + 2 ) ) abs(a_i - a_(i+2)) abs(ai−a(i+2))之中,通过观察可得。
Cpp代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++)
cin >> a[i];
if (n == 2)
{
return abs(a[1] - a[0]);
}
sort(a.begin(), a.end());
int ans = 0;
for (int i = 2; i < n; i += 2)
ans = max(ans, a[i] - a[i - 2]);
for (int i = 3; i < n; i += 2)
ans = max(ans, a[i] - a[i - 2]);
cout<<ans<<endl;
}
java代码
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scanner.nextInt();
}
if (n == 2)
{
System.out.println(Math.abs(a[1] - a[0]));
return ;
}
Arrays.sort(a);
int ans = 0;
for (int i = 2; i < n; i += 2)
ans = Math.max(ans, a[i] - a[i - 2]);
for (int i = 3; i < n; i += 2)
ans = Math.max(ans, a[i] - a[i - 2]);
System.out.println(ans);
}
}
python代码
if __name__ == "__main__":
n = int(input())
a = list(map(int, input().split()))
if n==2:
print(a[1]-a[0])
exit()
a.sort()
ans = 0
for i in range(2,n,2):
ans = max(ans,a[i]-a[i-2])
for i in range(3,n,2):
ans = max(ans,a[i]-a[i-2])
print(ans)