有 N� 座山排成一排,从左到右依次编号为 1∼N1∼�。
其中,第 i� 座山的高度为 hiℎ�。
对于一段连续的山脉,我们使用如下方法定义该段山脉的不对称值。
如果一段连续的山脉由第 l∼r�∼�(1≤l≤r≤N1≤�≤�≤�)座山组成,那么该段山脉的不对称值为 ∑0≤i≤r−l2|hl+i−hr−i|∑0≤�≤�−�2|ℎ�+�−ℎ�−�|。
现在,你需要回答 N� 个问题,问题编号 1∼N1∼�。
其中,第 i� 个问题的内容是:请计算,一段恰好包含 i� 座山的连续山脉(即长度为 i� 的连续区间)的不对称值的最小可能值。
输入格式
第一行包含一个整数 N�。
第二行包含 N� 个整数 h1,h2,…,hNℎ1,ℎ2,…,ℎ�。
输出格式
输出一行 N� 个整数,其中第 i� 个数表示第 i� 个问题的答案。
数据范围
1≤N≤50001≤�≤5000,
0≤hi≤1050≤ℎ�≤105
输入样例1:
7
3 1 4 1 5 9 2
输出样例1:
0 2 0 5 2 10 10
样例1解释
关于第 55 个问题的答案为什么是 22,见如下解析。
让我们依次列举所有长度为 55 的连续区间并计算区间不对称值:
- 区间 [3,1,4,1,5][3,1,4,1,5] 的不对称值为 |3−5|+|1−1|+|4−4|=2|3−5|+|1−1|+|4−4|=2。
- 区间 [1,4,1,5,9][1,4,1,5,9] 的不对称值为 |1−9|+|4−5|+|1−1|=9|1−9|+|4−5|+|1−1|=9。
- 区间 [4,1,5,9,2][4,1,5,9,2] 的不对称值为 |4−2|+|1−9|+|5−5|=10|4−2|+|1−9|+|5−5|=10。
由上可知,不对称值的最小可能值为 22。
输入样例2:
4
1 3 5 6
输出样例2:
0 1 3 7
样例2解释
注意,长度为 44 的连续区间只有 [1,3,5,6][1,3,5,6],其不对称值为 |1−6|+|3−5|=7|1−6|+|3−5|=7。
题解:
通过数据范围5000可以知道这道题最多需要使用O(n^2)的时间复杂度。
而我们可以通过找中心点来寻找答案,从中间向外扩展。时间复杂度O(n^2)
以下是代码:
#include<bits/stdc++.h>
using namespace std;
const int N=5010;
int f[N],h[N];
int n;
int main(){
cin>>n;
for(int i=0;i<n;i++) scanf("%d",&h[i]);
memset(f,0x3f,sizeof f);
for(int i=0;i<n;i++)
{
//奇数
for(int l=i,r=i,s=0;l>=0,r<n;l--,r++)
{
s+=abs(h[r]-h[l]);
f[r-l+1]=min(f[r-l+1],s);
}
//偶数
for(int l=i,r=i+1,s=0;l>=0,r<n;l--,r++)
{
s+=abs(h[r]-h[l]);
f[r-l+1]=min(f[r-l+1],s);
}
}
for(int i=1;i<=n;i++)
printf("%d ",f[i]);
return 0;
}