第一次写博客,emmmm,写的不好还望多多见谅。
这是一篇补题记录,也就是说蒟蒻我打比赛的时候并没有写出这道题。差分这玩意虽然理解起来并不算难,但是实际应用的时候还是需要一定的敏感度去意识到的,我是赛后在翻阅其他巨巨的交题记录是才猛然意识到这道题原来并不需要复杂的讨论之类的东西,只要做个差分数组然后sort一下就好。
题目链接如下
http://codeforces.com/problemset/problem/1197/C
题目大意:给出一个不下降序列a(前一项恒不大于后一项),再给出一个常数k,要求将a分成k段,设每一段首尾值之差为每一段的cost,求出采用使各段cost之和最小时的cost的总和。
差分数组:想要仔细学习的话可以自行找大佬的博客研读,这里只是简单解释一下,差分数组,也就是储存一列数前后元素之差的数组。
根据要求的值的性质(前后相减所得),我们可以想到尝试差分数组,这里求差分时我们可以把第一个元素设为0,也就是当作它和自己做了一次差分。此时我们可以发现,假如不分段,那我们要求的cost就是整个差分数组之和,而每将数组分出一段,cost就减少一个值,该值恰恰为我们分段时划分的那条边界上的差分值,比如我们将1~n分为1~j和j+1~n,那么cost的减少量就等于j+1处的原值(差分前的值)减去j处的原值,那么问题就转化成了如何减去最多的cost,这时候只要对差分数组sort排序,而后用数组总和减去前k-1大(众所周知,将一个数组分成k段只要划分k-1次)的元素和就可以得到答案。
上ac代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<set> 4 #include<stdio.h> 5 #include<string.h> 6 #include<math.h> 7 #include<vector> 8 #include<stdlib.h> 9 #include<queue> 10 #include<algorithm> 11 #include<map> 12 #include<stack> 13 using namespace std; 14 int a[300005]; 15 int n,k; 16 int main() 17 { 18 scanf("%d%d",&n,&k); 19 int be=-1; 20 int ans=0; 21 for(int i=0;i<n;i++) 22 { 23 scanf("%d",&a[i]); 24 if(be==-1) 25 { 26 be=a[i]; 27 a[i]=0; 28 } 29 else 30 { 31 a[i]-=be; 32 be+=a[i]; 33 } 34 ans+=a[i]; 35 } 36 sort(a,a+n); 37 for(int i=n-1;i>=0;i--) 38 { 39 if(k==1) 40 { 41 break; 42 } 43 else 44 { 45 k--; 46 ans-=a[i]; 47 } 48 } 49 printf("%d ",ans); 50 return 0; 51 }
希望对你有所帮助。