题目
小易老师是非常严厉的,它会要求所有学生在进入教室前都排成一列,并且他要求学生按照身高不递减的顺序排列。有一次,n个学生在列队的时候,小易老师正好去卫生间了。学生们终于有机会反击了,于是学生们决定来一次疯狂的队列,他们定义一个队列的疯狂值为每对相邻排列学生身高差的绝对值总和。由于按照身高顺序排列的队列的疯狂值是最小的,他们当然决定按照疯狂值最大的顺序来进行列队。现在给出n个学生的身高,请计算出这些学生列队的最大可能的疯狂值。小易老师回来一定会气得半死。
题解
首先考虑学生为偶数的情况,例如
1 500 1 500 1000 1 500 1
500 1 500 1 1 1000 1 500
我们可以选取,中间放最大值,然后按照一小一大的策略向两边展开,也可选择中间放最小值,然后按照一大一小的策略向两边展开。这两种策略最后的结果是相等的。
然后我们考虑学生为奇数的情况,例如
500 1 500 1 1000 1 1000 1 1000 1 1000 1 500 1 500
这时候,我们就需要分两种情况,中间放最大值和中间放最小值分别计算,然后取最大值。例如上面的例子,如果中间放最大值,就会造成1 500 1 500 1 1000 1 1000 1 1000 1 1000 1 500 500这样一个序列,这个序列的结果并不是最大值,因此我们需要考虑这两种序列,求最大值。
至于模拟过程,可以使用双端队列,这样最简单。
代码
#include <bits/stdc++.h>
#define LL long long
#define UP(i,l,h) for(int i=l;i<h;i++)
#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)
#define W(t) while(t)
#define MEM(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MAXN 60
#define COUT(x) cout<<x<<endl
using namespace std;
int a[MAXN];
deque<int> dq;
deque<int> ansdq;
int main(){
int n;
scanf("%d",&n);
UP(i,0,n){
scanf("%d",&a[i]);
}
sort(a,a+n);
int allans=0;
int ans=0;
UP(i,0,n) dq.push_back(a[i]);
ansdq.push_back(dq.back());
dq.pop_back();
bool small=true;
W(!dq.empty()){
if(small){
ans+=abs(dq.front()-ansdq.front());
// COUT(dq.front());
ansdq.push_front(dq.front());
dq.pop_front();
if(dq.empty()) break;
ans+=abs(dq.front()-ansdq.back());
// COUT(dq.front());
ansdq.push_back(dq.front());
dq.pop_front();
small=false;
}else{
ans+=abs(dq.back()-ansdq.front());
// COUT(dq.back());
ansdq.push_front(dq.back());
dq.pop_back();
if(dq.empty()) break;
ans+=abs(dq.back()-ansdq.back());
// COUT(dq.back());
ansdq.push_back(dq.back());
dq.pop_back();
small=true;
}
}
allans=ans;
ans=0;
dq.clear();
ansdq.clear();
UP(i,0,n) dq.push_back(a[i]);
ansdq.push_back(dq.front());
dq.pop_front();
small=false;
W(!dq.empty()){
if(small){
ans+=abs(dq.front()-ansdq.front());
ansdq.push_front(dq.front());
dq.pop_front();
if(dq.empty()) break;
ans+=abs(dq.front()-ansdq.back());
ansdq.push_back(dq.front());
dq.pop_front();
small=false;
}else{
ans+=abs(dq.back()-ansdq.front());
ansdq.push_front(dq.back());
dq.pop_back();
if(dq.empty()) break;
ans+=abs(dq.back()-ansdq.back());
ansdq.push_back(dq.back());
dq.pop_back();
small=true;
}
}
// COUT(ans);
allans=max(ans,allans);
printf("%d\n",allans);
}