序列
题目描述
有一个整数序列,它的每个数各不相同,我们不知道它的长度是多少(即整数个数),但我们知道在某些区间中间至少有多少个整数,用区间( L i , R i , C i L_i,R_i,C_i Li,Ri,Ci)来描述,表示这个整数序列中至少有 C i C_i Ci 个数来自区间 [ L i , R i ] [L_i,R_i] [Li,Ri],给出若干个这样的区间,问这个整数序列的长度最少能为多少?
输入格式
第一行一个整数 N N N,表示区间个数;
接下来 N N N 行,每行三个整数 L i , R i , C i L_i,R_i,C_i Li,Ri,Ci,描述一个区间。
输出格式
仅一个数,表示该整数序列的最小长度。
样例 #1
样例输入 #1
4
4 5 1
6 10 3
7 10 3
5 6 1
样例输出 #1
4
提示
数据范围及约定
对于全部数据, 1 ≤ N ≤ 1000 1\le N \le 1000 1≤N≤1000, 0 ≤ L i ≤ R i ≤ 1000 0 \le L_i \le R_i \le 1000 0≤Li≤Ri≤1000, 1 ≤ C i ≤ R i − L i + 1 1 \le C_i \le R_i-L_i+1 1≤Ci≤Ri−Li+1。
思路
- 我们通过举例发现,交界处最好放数字在重叠部分,这样就可以使得数最少。
- 此时我们可以枚举左端点,因为本道题是给定每个区间的限制说用区间( L i , R i , C i L_i,R_i,C_i Li,Ri,Ci)来描述,表示这个整数序列中至少有 C i C_i Ci 个数来自区间 [ L i , R i ] [L_i,R_i] [Li,Ri],因此我们得用 c n t cnt cnt 来记录每个区间是否满足每个区间的限制,然后,我们要统计这个区间已有的数(用一个 bool 类型的数组来标记安排数的地方),判断是否满足这个区间所需的数:满足,则跳至下一个区间;不满足,则继续安排数的人。(为什么呢?因为每个区间的条件都得要满足)。
- 如果不满足,从后往前找到未有数的位置(后面的位置越容易与另一个区间重合),给他分配空间。每安排下一个数,最终结果加一,这个区间的数加一,直至本区间的数满足要求。
代码
/*
1 2 3 4 5 6 7 8 9 10
|-|
1
|-|
1
|--------|
3
|------|
3
最短长度就是 5 6 7 8
贪心策略:尽量在交界地方放元素,保证元素的总个数最少
所以我们对左端点进行排序
*/
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1010;
struct E{
int x,y,w;
bool operator<(const E& t)const{
return x<t.x;
}
}e[N];
int n;
int ans,cnt;
bool st[N];
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>e[i].x>>e[i].y>>e[i].w;
}
sort(e+1,e+1+n);
for(int i=n;i>=1;i--){
// cout<<e[i].x<<" "<<e[i].y<<endl;
cnt=0;//代表现在区间内已经有cnt个数了
for(int j=e[i].y;j>=e[i].x;j--){//统计之前已有数的个数。
if(st[j]){
cnt++;
}
}
if(cnt>=e[i].w)continue;//如果已经满足这个区间的约束,那么就不用再加了,开始看下一个区间
for(int j=e[i].x;j<=e[i].y;j++){
if(!st[j]){
cnt++;
ans++;
st[j]=true;
if(cnt>=e[i].w)break;
}
}
}
cout<<ans;
return 0;
}