题目链接:http://codeforces.com/problemset/problem/1197/C
大意
给一个长为
n
n
n的单调不下降数组,将数组划分为k段,使得每段的【最大值与最小值之差】之和最小。
思路
乍一看没什么头绪。
(去吃了个饭)
仔细思考后发现设第
k
k
k段开头为
a
l
a_l
al,结尾为
a
r
a_r
ar则这段的最小值与最大值之差可以表示为
(
(
a
((a
((al+1
−
a
-a
−al
)
+
(
a
)+(a
)+(al+2
−
a
-a
−al+1
)
+
…
…
+
(
a
)+……+(a
)+……+(ar
−
a
-a
−ar-1
)
)
))
))又整个数列的最大值与最小值之差可以表示为
(
(
a
((a
((a2
−
a
-a
−a1
)
+
(
a
)+(a
)+(a3
−
a
-a
−a2
)
+
…
…
+
(
a
)+……+(a
)+……+(an
−
a
-a
−an-1
)
)
))
))共
n
−
1
n-1
n−1个值,则划分
k
k
k个区间相当于从
(
(
a
((a
((a2
−
a
-a
−a1
)
,
(
a
),(a
),(a3
−
a
-a
−a2
)
,
…
…
,
(
a
),……,(a
),……,(an
−
a
-a
−an-1
)
)
))
))中去掉
k
−
1
k-1
k−1个值。故只需求得原数组中最大值与最小值的差
d
i
s
=
a
dis=a
dis=an
−
a
-a
−a1,再求得每两个元素之差(共
n
−
1
n-1
n−1个)并对其排序,用
d
i
s
dis
dis减去最大的
k
−
1
k-1
k−1个差值即得答案。
AC代码
#include<algorithm>
#include<stdio.h>
using namespace std;
int a[300005],n,k,ans;
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
ans=a[n]-a[1];
for(int i=1;i<n;i++)a[i]=a[i+1]-a[i];
sort(a+1,a+n);
k--;
for(int i=n-1;k;i--,k--)ans-=a[i];
printf("%d",ans);
return 0;
}