一条街道的一边有几座房子。因为环保原因居民想要在路边种些树,路边的地区被分割成n块,并被编号为1…n,每块大小为一个单位尺寸并最多可种一棵树。每个居民想在门前种些树并指定了三个数b,e,t这三个数分别表示该居民想在b和e之间最少种t棵树,当然,b≤e,t≤e-b+1,允许居民想种树的子区域可以交叉。出于资金紧缺的原因,环保部门请你求出能够满足所有居民的种树要求时所需要种的树的最少数量。
输入格式:
第一行为n,表示区域的个数。
第二行为h,表示房子的数目。
下面h行描述居民的需要:b、e、t(0<b≤e≤30 000,t≤e-b+1)分别用一个空格分开。
输出格式:
输出一个数,为满足所有居民的要求,所需要种树的最少数量。
输入样例:
9
4
1 4 2
4 6 2
8 9 2
3 5 2
输出样例:
5
数据规模:
30%的数据满足 0<n≤l 000;0<h≤500。
100%的数据满足 n≤30 000;h≤5 000, 0<b≤e≤30 000,t≤e-b+1。
解题思路
- 将区间按右端点从小到大进行排序
- 将树尽量种在公共区域,即区间右端
- 重叠部分处理,做一个标志,若以种树,则该区间所需树减一。
代码实现
#include<iostream>
#include<algorithm>//快排头文件
using namespace std;
struct Shu{
int l;
int r;
int val;//所需种树棵树
};
int cmp(Shu a,Shu b){
return a.r<b.r;
}
int main(){
int i,j,h,n,arr[300005];
long long ans=0;
Shu s[300005];
cin>>n>>h;
for(i=0;i<h;i++){
cin>>s[i].l>>s[i].r>>s[i].val;
}
for(i=0;i<n;i++){
arr[i]=0;//用arr数组存放是否种树标志,1为已种
}
sort(s,s+h,cmp);
for(i=0;i<n;i++){
for(j=s[i].l;j<=s[i].r&&s[i].val>0;j++){//先判断该区间是否有种树,相当于统计上个区间与该区间重合部分树的数量。
if(arr[j]==1){
s[i].val--;
}
}
for(j=s[i].r;j>=s[i].l&&s[i].val>0;j--){
if(arr[j]==0){
arr[j]=1;
s[i].val--;
ans++;
}
}
}
cout<<ans;
return 0;
}