我是靠谱客的博主 甜美小丸子,最近开发中收集的这篇文章主要介绍P1250 种树,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

P1250 种树

题目背景

一条街的一边有几座房子,因为环保原因居民想要在路边种些树。

题目描述

路边的地区被分割成块,并被编号成 1 , 2 , … , n 1, 2, ldots,n 1,2,,n。每个部分为一个单位尺寸大小并最多可种一棵树。

每个居民都想在门前种些树,并指定了三个号码 b b b e e e t t t。这三个数表示该居民想在地区 b b b e e e 之间(包括 b b b e e e)种至少 t t t 棵树。

居民们想种树的各自区域可以交叉。你的任务是求出能满足所有要求的最少的树的数量。

输入格式

输入的第一行是一个整数,代表区域的个数 n n n

输入的第二行是一个整数,代表房子个数 h h h

3 3 3 到第 ( h + 2 ) (h + 2) (h+2) 行,每行三个整数,第 ( i + 2 ) (i + 2) (i+2) 行的整数依次为 b i , e i , t i b_i, e_i, t_i bi,ei,ti,代表第 i i i 个居民想在 b i b_i bi e i e_i ei 之间种至少 t i t_i ti 棵树。

输出格式

输出一行一个整数,代表最少的树木个数。

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

数据规模

对于 100 % 100% 100% 的数据

  • 1 ≤ n ≤ 3 × 1 0 4 1 leq n leq 3 times 10^4 1n3×104 1 ≤ h ≤ 5 × 1 0 3 1 leq h leq 5 times 10^3 1h5×103
  • 1 ≤ b i ≤ e i ≤ n 1 leq b_i leq e_i leq n 1biein 1 ≤ t i ≤ e i − b i + 1 1 leq t_i leq e_i - b_i + 1 1tieibi+1

题解

我们将各个要求按右端点从小到大排序,如果右端点相同则按左端点从大到小排序,然后依次判断每个一段是否满足至少有 t t t棵树。如果不满足,则从右开始种树,直到满足为止。因为右端点从小到大,所以种在右边一定比左边更优。所以这样做的结果一定最优。

每一段处理时间复杂度为 O ( n ) O(n) O(n),所以总时间复杂度为 O ( n h ) O(nh) O(nh),但跑不满,所以还是可以过的。用链表维护没有种树的区域,用树状数组来单点修改和区间查询,时间复杂度可将为 O ( n + h l o g   n ) O(n+hlog n) O(n+hlog n)

code

#include<bits/stdc++.h>
using namespace std;
int n,h,ans,z[30005];
struct node{
int x,y,t;
}w[5005];
bool cmp(node ax,node bx){
if(ax.y!=bx.y) return ax.y<bx.y;
return ax.x>bx.x;
}
int main()
{
scanf("%d%d",&n,&h);
for(int i=1;i<=h;i++)
scanf("%d%d%d",&w[i].x,&w[i].y,&w[i].t);
sort(w+1,w+h+1,cmp);
for(int i=1;i<=h;i++){
for(int j=w[i].x;j<=w[i].y&&w[i].t;j++) w[i].t-=z[j];
if(w[i].t>0){
for(int j=w[i].y;j>=w[i].x&&w[i].t;j--){
if(!z[j]){
z[j]=1;--w[i].t;
}
}
}
}
for(int i=1;i<=n;i++) ans+=z[i];
printf("%d",ans);
}

最后

以上就是甜美小丸子为你收集整理的P1250 种树的全部内容,希望文章能够帮你解决P1250 种树所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部