2019.12.4 种树

种树

题目描述

某条街被划为 \(n\) 条路段,这 \(n\) 条路段依次编号为 \(1\dots n\)。每个路段最多可以种一棵树。现在居民们给出了 \(h\) 组建议,每组建议包含三个整数 \(b,e,t\),表示居民希望在路段 \(b\)\(e\) 之间至少要种 \(t\) 棵树。这些建议所给路段的区间可以交叉。请问:如果要满足所有居民的建议,至少要种多少棵树。

输入格式

第一行为 \(n\),表示路段数。

第二行为 \(h\),表示建议数。

下面 \(h\) 行描述一条建议:\(b, e, t\),用一个空格分隔。

输出格式

输出只有一个数,为满足所有居民的建议,所需要种树的最少数量。

输入输出样例

样例输入
9
4
1 4 2
4 6 2
8 9 2
3 5 2
样例输出
5

数据范围与提示

\(30\%\) 的数据满足 \(0<n\le 1000\)\(0<h\le 500\)

\(100\%\) 的数据满足 \(0<n\le 3\times 10^4\)\(h\le 5000\)\(0<b\le e\le 3\times 10^4\)\(t\le e-b+1\)

尽可能将每棵树贡献到答案里尽量多,所以我们按照右端点排序,再尽可能往右边种。每次先扫描这个区间里面已经种上了几棵,从右往左补齐剩下的即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cctype>
#define int long long
#define rep(i,a,n) for(register int i=a;i<=n;++i)
#define dwn(i,n,a) for(register int i=n;i>=a;--i)
using namespace std;
int h,n,book[100050];
struct node
{
	int b,e,t;
}a[100050];
inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
void write(int x)
{
	if(x<0)putchar('-'),x=-x;
	if(x==0)return;
	write(x/10);
	putchar(x%10+'0');
}
bool cmp(node a,node b)
{
	if(a.e==b.e)return a.b<b.b;
	return a.e<b.e;
}
signed main()
{
	n=read(),h=read();
	rep(i,1,h)a[i].b=read(),a[i].e=read(),a[i].t=read();
	sort(a+1,a+h+1,cmp);
	rep(i,1,h)
	{
		int cnt=0;
		rep(j,a[i].b,a[i].e)cnt+=book[j];
		if(cnt>=a[i].t)continue;
		dwn(j,a[i].e,a[i].b)
		{
			if(!book[j])
			{
				book[j]=1;
				++cnt;
			}
			if(cnt==a[i].t)break;
		}
	}
	int cnt=0;
	rep(i,1,n)cnt+=book[i];
	if(cnt)write(cnt);
	else putchar('0');
	return 0;
}
/*
9
4
1 4 2
4 6 2
8 9 2
3 5 2
*/
posted @ 2019-12-04 17:47  lqxssf  阅读(247)  评论(0编辑  收藏  举报