题目描述
小明要做一个篱笆,篱笆由N块高度不同的木条组成,我们定义它的好看程度为相邻的篱笆的高度差的绝对值之和。小明已经买好了木条,但它不知道要如何安排顺序,才能使他的篱笆与小华的相似,并且尽量好看。
我们认为两个篱笆相似当且仅当两个篱笆的高低变化情况一致。即如果一个篱笆中的第i块木条高于第i+1块,则另一个篱笆中的第i块也高于第i+1块,则认为它们相似。
给出小华的篱笆信息,和小明买到的每块木板的长度,现在要求出小明的解决方案,使得他的篱笆与小华的相似,且尽量好看。如果有多种解决方案,任意输出一种即可。
输入
第一行一个整数N(2<=N<=300000),表示木条的数量。
第二行是N个不同的正整数,表示小华的篱笆。
第三行N个不同的正整数,表示小明的木板。
输出
第一行:一个整数,表示篱笆的好看程度。
第二行是N个不同的正整数,表示小明的篱笆。
样例输入
4
5 7 4 9
1 2 3 4
样例输出
7
2 4 1 3
考试时被吓到了,好恐怖的题,打了题目的表,马上换下一题,结果全Wa /(ㄒoㄒ)/~~
老师评讲后,才明白了,这是一道贪心的题目,就样例数据来看,可以先把小华的篱笆画出来
这…………有美感吗?
言归正传
首先,我们来砍一下美感值是如何计算的,为两栅栏的绝对值,这时可以发现,一组栅栏的美感值只取决于起伏的顶端和底端,与中间的没有关系,于是,我们把栅栏看做一条山脉,看它的山脉走向(打开方式好像不对,怎么扯到地理了)…………看它的峰顶和山谷,用int数组来记录,除两边末端的栅栏外,其他都要使用两次(左边和右边),所以峰顶越高,山谷越低,美感值就越高,
于是将小明的木板从小到大排序,越高的放山峰,越低的放山谷,两端再凭其走向放置,再计算其美感值,剩下的木板凭走向放置,一一输出,KO!
实在不懂,丢代码了:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[300005],v[300005],e[300005],b[300005];
int n,s;
void scan()
{
int i;
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&b[i]);
for(i=2;i<n;i++)
{
if(b[i]>b[i-1]&&b[i]>=b[i+1])v[i]=2;//峰顶
if(b[i]<b[i-1]&&b[i]<=b[i+1])v[i]=-2;//山谷
}
if(b[1]<b[2])v[1]=-1;//看两端
else v[1]=1;
if(b[n]<b[n-1])v[n]=-1;
else v[n]=1;
for(i=1;i<=n;i++)scanf("%d",&a[i]);
sort(a+1,a+n+1);//给小明的木板排序
}
void work()
{
int i,l=1,r=n;
for(i=2;i<n;i++)
{
if(v[i]==2)e[i]=a[r--],s+=2*e[i];//峰顶取最大
if(v[i]==-2)e[i]=a[l++],s-=2*e[i];//山谷取最小
}
if(v[1]==1)e[1]=a[r--],s+=e[1];//再考虑两端
else e[1]=a[l++],s-=e[1];
if(v[n]==1)e[n]=a[r--],s+=e[n];
else e[n]=a[l++],s-=e[n];
for(i=2;i<n;i++)//填中间的木板
if(!v[i])
{
if(b[i-1]<b[i]) e[i]=a[l++];//看走向
else e[i]=a[r--];
}
}
int main()
{
int i;
scan();
work();
printf("%d\n",s);
int f=0;
for(i=1;i<=n;i++)
{
if(!f)f=1;
else printf(" ");//好习惯,行末无空格~\(≧▽≦)/~
printf("%d",e[i]);
}
}