前言
(大雾 一群神仙构造拆式子。我乱搞想骗分的贪心没有WA就离谱。顺便吐槽一下题意好难懂。我做题得跟用来判SPJ的checker.cpp一起看就离谱。另外祝大家1月1日新年快乐。
题目大意
需要在一条笔直的路上建 个法阵,编号为 。
给定一个长度为 的数组 ,表示在 到 的位置建法阵,要给法阵编号。
需要来检测法阵效果,从 号法阵走到 号,从 号再走到 号,直到走到 号,再从 号走回 号。
由于法阵的特殊效果,从 个走到 个的距离是 。特别的,从 号走回到 号的距离是 。 是给定的两个常数, 是两个法阵的位置。
来求一下最大的行走距离,并输出对应法阵从 号到 号排列方法。
对于 的数据满足 ,,。
思路
暴力深搜 ,肯定T飞了。考虑优化。由于出题人连大样例的构造方式都不给了,小样例又特别水,所以可以猜测本题应该不会十分困难。
感觉本题好像可以贪心的样子,也没啥其他的思路了,想想试试。如果要贪心,那我就按照这样构造试试:
- 找最大的放到新序列里
- 找最小的放到新序列里
- 从 中删除这两个数
听着很绕,其实就是按照一大一小一大一小···这样排序。测一下小样例,发现不对。然后发现上述情况没有考虑 ,感觉这是不是错的原因。之后发现,如果 更大,那么按照小大小大···这么排序更好,因为这可以让大数变得更大,就算大的很小也不亏。所以分类讨论。当 时按照前者进行运算,否则按照后者进行。
时间复杂度 。
代码
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll MAXN=1e6+5;
ll n,p,q,a[MAXN],b[MAXN];
bool cmp(ll A,ll B){
return A>B;
}
int main(){
cin>>n;
cin>>p>>q;
for (int i = 1; i <=n ; ++i) {
cin>>a[i];
}
if(p>q){
sort(a+1,a+n+1);
}else{
sort(a+1,a+n+1,cmp);
}
ll l=1,r=n;
ll sz=0;
while (l<=r){
b[++sz]=a[l];//放最小/大的
b[++sz]=a[r];//放最大/小的
l++;
r--;
}
ll ans=0;
for (int i = 1; i <n ; ++i) {
ans+= abs(b[i]*p-b[i+1]*q);
}
ans+= abs(b[n]*p-b[1]*q);
cout<<ans<<endl;
for (int i = 1; i <=n ; ++i) {
printf("%lld ",b[i]);
}
return 0;
}
总结
通过了分析题面和大胆猜测的出了贪心的做法。同时在经过错误后的分析得出了正解。