网课:第二章模拟、枚举与贪心---校门外的树

题目描述

某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,......,L,都种有一棵树。

由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树都移走后,马路上还有多少棵树。

输入描述:

复制代码
第一行有两个整数:L(1 <= L <= 10000)和 M(1 <= M <= 100),L代表马路的长度,M代表区域的数目,L和M之间用一个空格隔开。接下来的M行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点和终止点的坐标。

输出描述:

复制代码
包括一行,这一行只包含一个整数,表示马路上剩余的树的数目。

示例1

输入

复制500 3 150 300 100 200 470 471

复制代码
500 3
150 300
100 200
470 471

输出

复制298

复制代码
298

备注:

复制代码
对于20%的数据,区域之间没有重合的部分;
对于其它的数据,区域之间有重合的情况。

想法:

解法一:

差分。对一个区间操作会超时,用差分处理区间的两端即可。

复制代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
int cf[10010];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        cf[a]--;//
        cf[b+1]++;//
    }
    int ans=0;
    int a=1;
    for(int i=0;i<=n;i++){
        a=a+cf[i];
        if(a>0) ans++;
    }
    cout<<ans;
}

wa的原因:

处理cf数组时用-1和1标记了,但会出现端点重叠的情况(如0,0,1,0,1,0,0,-1),这就不对了。所以得用++和--。

解法二:

合并区间,将总数减去各个不同的区间。

复制代码
//怎么合并成一个大区间
//排序,然后看这个右端点是否在下一个的左右端点之间,是的话可以合并为一个区间
#include<bits/stdc++.h>
using namespace std;
int n,m;
struct ty{
    int l,r;  
};
bool cmp(ty a,ty b){
    if(a.l==b.l) return a.r<b.r;
    return a.l<b.l;
}
int main(){
    scanf("%d%d",&n,&m);
    vector<ty> v,g;
    for(int i=0;i<m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        v.push_back({a,b});
    }
    sort(v.begin(),v.end(),cmp);
    for(int i=0;i<m;i++){
        int l=v[i].l,r=v[i].r;
        int cnt=0;
        for(int j=i+1;j<m;j++){
            if((r>=v[j].l&&r<=v[j].r)||(l<=v[j].l&&r>=v[j].r)){
                cnt++;
                r=max(v[j].r,r);
                l=min(v[j].l,l);
            }
            else break;
        }
        i+=cnt;
        g.push_back({l,r});
    }
    int ans=n+1;
    for(int i=0;i<g.size();i++){
        ans-=g[i].r-g[i].l+1;
    }
    cout<<ans;
}

wa的原因:

1.cnt忘加了,导致合并区间的时候多出了几个区间。

2.可以合并成一个大区间的情况考虑少了,只考虑到相交,没考虑到前一个区间把后一个区间包起来的情况。乱造数据时发现的

500 10

0 100

100 200

159 300

300 456

2 50

3 111

498 500

234 333

111 112

123 321

输出是负数

相关推荐
Jerry3 分钟前
LeetCode 459. 重复的子字符串
算法
海石3 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石3 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
Jerry5 小时前
LeetCode 151. 反转字符串中的单词
算法
a1117767 小时前
LM 算法迭代过程动画演示(SLAM)
算法
头茬韭菜7 小时前
Context 的生死抉择:四层压缩、截断算法与 Session Memory
算法·ai
Jerry7 小时前
LeetCode 541. 反转字符串 II
算法
Jerry8 小时前
LeetCode 344. 反转字符串
算法
搞科研的小刘选手8 小时前
【香港大学主办&IEEE出版】第六届计算机视觉、应用与算法国际学术会议(CVAA 2026)
算法·计算机视觉·应用·学术会议
Java小白笔记8 小时前
Codex config.toml配置实战指南
人工智能·算法·chatgpt·ai编程·集成学习