cf global 1 B greedy sortings 1400

原文题目
You have a long stick, consisting of m segments enumerated from 1 to m. Each segment is 1 centimeter long. Sadly, some segments are broken and need to be repaired.

You have an infinitely long repair tape. You want to cut some pieces from the tape and use them to cover all of the broken segments. To be precise, a piece of tape of integer length t placed at some position s will cover segments s,s+1,…,s+t−1.

You are allowed to cover non-broken segments; it is also possible that some pieces of tape will overlap.

Time is money, so you want to cut at most k continuous pieces of tape to cover all the broken segments. What is the minimum total length of these pieces?

Input
The first line contains three integers n, m and k (1≤n≤105, n≤m≤109, 1≤k≤n) — the number of broken segments, the length of the stick and the maximum number of pieces you can use.

The second line contains n integers b1,b2,…,bn (1≤bi≤m) — the positions of the broken segments. These integers are given in increasing order, that is, b1<b2<…<bn.

Output
Print the minimum total length of the pieces.

原文题意
给了三个数,n,m,k,分别代表数组的元素个数,棍的长度,最多用的胶带段数,数组中储存的是木棍的断点位置,求该怎么样可以把木棍用给定的段数连接起来,求出所用的胶带的长度,胶带可以重合

题解
题中给的是一个顺序递增的数组,而我们如果想要把木棍连接起来,那么断点之间莲的肯定是离它最近的断点,当然,如果都比较远,那么连的就是它自己,这时候只需要一点胶带的长度。
我们可以发现一个问题,胶带的段数越多,那么需要的总胶带长度就越短,因为极限情况是每一个断点都只连自己那个长度为1的地方,同理如果胶带段数比较少的时候,总长度就不可避免的变多。
那么,如果要连,肯定是连距自己最近的,也就是左边的一个或者右边的一个,所以我们可以直接求这个数组前缀差值,这个差值就是连接所需要的长度,我们将这个差值的数组排序,从小到大一次相加。注意,我们只需要加前n-k个就可以了,因为胶带数越多,胶带总长越短,n-k代表有n-k个需要相连,即前n-k小的段数是相连的,而后面的我们偶读单个相加就可以了,所以最后的总和再加上k即可
我们以数据
4 100 2
20 30 75 80
为例,他们的差值是10 45 5
5 100 2
20 30 75 80 100
的差值是 10 45 5 20
我们可以看到,在第一个用例中,只需要两段就可以连接完毕,而第二个用例因为多了一个断点,所以所需要的连接数也增加一个,而这个连接数始终和n-k是相等的,n-k可以保证胶带的段数始终是两段
而加k是因为,每一段都会有两个断点,而断点是有一个单位长度的,所以要加上胶带数

#include <bits/stdc++.h>
using namespace std;
int a[100005];
int cha[100005];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,i,j,k,t,m;
    long long s=0;
    cin>>n>>m>>k;
    for(i=0;i<n;i++)
        cin>>a[i];
    for(i=1;i<n;i++)
        cha[i-1]=a[i]-a[i-1];
    sort(cha,cha+n-1);
    //for(i=0;i<n-k;i++)
      //  cout<<cha[i]<<endl;
    for(i=0;i<n-k;i++)
        s=s+cha[i];
    cout<<s+k<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值