Fence
我们可以想象一个东西,叫做“贡献值”,指的是每一个板子相对于相邻的两个板子的一个特定的值。比方说:如下图:中间的红色板子明显低于其他的两个板子,所以我们在计算它的“友好值”的时候(我们把从左到右的三个板子的高度分别标为A/B/C),是A-B+C-B,等于说,中间的这个板子被减去了两次。于是我们可以把中间的板子的“贡献值”标为-2.
同理,对于下面这张图,左边的板子高于它,右边的板子低于它,我们算贡献值的时候,是A-B+B-C,可以说,B被抵消了。于是中间这个板子的贡献值为0。
同理,下面这张图的友好值为B-A+B-C,贡献值为2.
当我们计算左右端点的时候,如果说端点板子低于相邻的板子,则友好值为:A-B(或者C-B),它的贡献值为-1;当端点板子高于相邻的板子时,友好值为B-A(或者B-C)。
至此,我们发现,一个木板的贡献值有五种:-2 -1 0 1 2。我们要做的,只是对要操作的木板进行分类。
例如:我们输入一组数据:
10
9 5 1 2 6 7 4 18 20 12
10 40 20 30 50 70 80 100 1000 500
它的标准是9 5 1 2 6 7 4 18 20 12.
我们按照贡献值分一下类:
1 0 -2 0 0 2 -2 0 2
所以,我们要对输入数据的第三排进行排序,以达到每一个数据它在数组中的贡献值等于标准中的贡献值。
标程如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,a[300001],b[300001];
int ding,gu;
long long ans=0;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
sort(b+1,b+1+n);
for(int i=2;i<n;i++){
if(a[i]<a[i-1]&&a[i]<a[i+1])
gu++,ans-=b[gu]*2;//求两端高中间低的点.
if(a[i]>a[i-1]&&a[i]>a[i+1])
ding++,ans+=b[n-ding+1]*2;//求两端低中间高的点
}
if(a[1]>a[2]) ding++,ans+=b[n-ding+1];//由于第一个和最后一个没有连接两个点,所以需要特判
else gu++,ans-=b[gu];
if(a[n]>a[n-1]) ding++,ans+=b[n-ding+1];
else gu++,ans-=b[gu];
cout<<ans;//输出就行
return 0;
(以上标称出自此大佬@only_xiaohuang)