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
*/

猜你喜欢

转载自www.cnblogs.com/qxds/p/11984411.html