链接:https://www.nowcoder.com/questionTerminal/d996665fbd5e41f89c8d280f84968ee1
编程题]疯狂队列
- 热度指数:11064 时间限制:1秒 空间限制:32768K
- 算法知识视频讲解
小易老师是非常严厉的,它会要求所有学生在进入教室前都排成一列,并且他要求学生按照身高不递减的顺序排列。有一次,n个学生在列队的时候,小易老师正好去卫生间了。学生们终于有机会反击了,于是学生们决定来一次疯狂的队列,他们定义一个队列的疯狂值为每对相邻排列学生身高差的绝对值总和。由于按照身高顺序排列的队列的疯狂值是最小的,他们当然决定按照疯狂值最大的顺序来进行列队。现在给出n个学生的身高,请计算出这些学生列队的最大可能的疯狂值。小易老师回来一定会气得半死。
输入描述:
输入包括两行,第一行一个整数n(1 ≤ n ≤ 50),表示学生的人数
第二行为n个整数h[i](1 ≤ h[i] ≤ 1000),表示每个学生的身高
输出描述:
输出一个整数,表示n个学生列队可以获得的最大的疯狂值。
如样例所示:
当队列排列顺序是: 25-10-40-5-25, 身高差绝对值的总和为15+30+35+20=100。
这是最大的疯狂值了。
示例1
输入
5
5 10 25 40 25
输出
100
用双端队列模拟
贪心构造,首先把最大的一个放进去,然后每次抽取一个最大/最小,贪心的思路是,每次放进去队列的头或者尾,也就是左边
或者右边,差值最大。
模拟一次即可。
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
deque<int> que;
multiset<int> ss[2];
multiset<int> :: iterator it;
int did(int id) {
int ans = 0;
while (!ss[id].empty()) {
int mx = -inf;
it = ss[id].begin();
mx = max(mx, abs(*it - que.front()));
mx = max(mx, abs(*it - que.back()));
it = ss[id].end();
it--;
mx = max(mx, abs(*it - que.front()));
mx = max(mx, abs(*it - que.back()));
ans += mx;
if (abs(*it - que.front()) == mx) {
que.push_front(*it);
ss[id].erase(it);
continue;
} else if (abs(*it - que.back()) == mx) {
que.push_back(*it);
ss[id].erase(it);
continue;
}
it = ss[id].begin();
if (abs(*it - que.front()) == mx) {
que.push_front(*it);
ss[id].erase(it);
continue;
} else {
que.push_back(*it);
ss[id].erase(it);
continue;
}
}
return ans;
}
void work() {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
int val;
cin >> val;
ss[0].insert(val);
ss[1].insert(val);
}
it = ss[0].end();
--it;
que.push_back(*it);
ss[0].erase(it);
int ans1 = did(0);
printf("%d\n", ans1);
}
int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
work();
return 0;
}
View Code