原题链接:https://codeforces.com/problemset/problem/1110/B?tdsourcetag=s_pcqq_aiomsg
You have a long stick, consisting of mm segments enumerated from 11 to mm . Each segment is 11centimeter 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 tt placed at some position ss will cover segments s, s+1, \ldots, s+t-1s,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 kk continuous pieces of tape to cover all the broken segments. What is the minimum total length of these pieces?
输入输出格式
输入格式:
The first line contains three integers nn , mm and kk ( 1 \le n \le 10^51≤n≤105 , n \le m \le 10^9n≤m≤109 , 1 \le k \le n1≤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 nn integers b_1, b_2, \ldots, b_nb1,b2,…,bn ( 1 \le b_i \le m1≤bi≤m ) — the positions of the broken segments. These integers are given in increasing order, that is, b_1 < b_2 < \ldots < b_nb1<b2<…<bn .
输出格式:
Print the minimum total length of the pieces.
输入输出样例
6
题意总结:
先给你三个数n,m,k,分别表示点数,总长度,胶带的数量,再给你n个点,保证数是递增的。求覆盖所有的点所需的最小胶带长度(胶带数量 <= k)
思路:
首先,这题中每一个点都是需要被覆盖的
在胶带数量 k=n 的情况下,只需要覆盖每个点即可,此时最小长度就是n
否则的话,每少用一个胶带代表会有两个相邻的点要使用同一个胶带覆盖即需要覆盖这两个点之前的区间(不包括端点,即开区间)的长度 b[i]−b[i−1]−1
到了这里我们就可以贪心了
不难发现,只要每次取最小的区间直到胶带数满足要求即可
而需要取的区间数量即为n-k(两个区间可能连续,例如1,2,3,10。 则取区间1到3,然后加上点10,即最小长度就是4,因为计算的是开区间,所以在没加上区间点数之前区间是不连续的,具体看代码解释)
最后加上点数n即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+10;
const ll INF = 0x3f3f3f3f;
ll n,m,k,sum = 0;
ll a[N] = {0};
ll b[N] = {0};
int main(){
cin>>n>>m>>k;
k = n-k; // k为需要的区间数量
for(int i = 1;i <= n;i ++){
cin>>a[i];
b[i-1] = a[i]-a[i-1]-1; // 计算每个区间长度
}
sort(b+1,b+n); // 从小到大排序(注意只有n-1个区间)
for(int i = 1; i <= k; i ++){
sum += b[i]; // 覆盖区间
}
cout<<sum+n<<endl; // 最后加上所有的端点就是最终答案
return 0;
}