题目描述
某条街被划为 n 条路段,这 n 条路段依次编号为 1…n。每个路段最多可以种一棵树。现在居民们给出了 h 组建议,每组建议包含三个整数 b,e,t,表示居民希望在路段 b 到 e 之间至少要种 t棵树。这些建议所给路段的区间可以交叉。请问:如果要满足所有居民的建议,至少要种多少棵树。
输入格式
第一行为 n,表示路段数。
第二行为 h,表示建议数。
下面 h 行描述一条建议:b, e, t,用一个空格分隔。
输出格式
输出只有一个数,为满足所有居民的建议,所需要种树的最少数量。
样例
Inputcopy | Outputcopy |
---|---|
9 4 1 4 2 4 6 2 8 9 2 3 5 2 | 5 |
数据范围与提示
30\%30% 的数据满足 0<n\le 10000<n≤1000,0<h\le 5000<h≤500;
100\%100% 的数据满足 0<n\le 3\times 10^40<n≤3×104,h\le 5000h≤5000,0<b\le e\le 3\times 10^40<b≤e≤3×104,t\le e-b+1t≤e−b+1。
思路:先按结束的先后从小到大排序,接着每次将数从区间的最后开始种植,然后在种植前要遍历一遍该区间,看看是否已经种了一部分数了,若没达到建议数,从区间结尾开始种植,若达到甚至是超过了,就不用再在该区间种植树了。
#include<stdio.h>
struct move{
int b;
int e;
int t;
}k[5000];
int main()
{
int n,h,i,j,l,sum=0,w=0;
struct move s;
scanf("%d",&n);
scanf("%d",&h);
for(i=0;i<h;i++)
{
scanf("%d %d %d",&k[i].b,&k[i].e,&k[i].t);
}
int count[30000];
//每条街道最开始都是0棵树
for(i=0;i<n;i++)
{
count[i]=0;
}
//按结尾的先后顺序排序
for(i=0;i<h-1;i++)
{
for(j=i+1;j<h;j++)
{
if(k[i].e >k[j].e )
{
s=k[i];
k[i]=k[j];
k[j]=s;
}
}
}
//
for(i=0;i<h;i++)//第几条建议
{
w=0;
for(l=k[i].e -1;l>=k[i].b -1;l--)
{
if(count[l]==1)
{
w++;
}
}
if(w>=k[i].t ) continue;
for(l=k[i].e -1;l>=k[i].b -1;l--)
{
if(count[l]!=1)
{
count[l]=1;
w++;
if(w>=k[i].t) break;
}
}
}
for(i=0;i<n;i++)
{
sum+=count[i];
}
printf("%d",sum);
return 0;
}