CSP历年复赛题-P1047 [NOIP2005 普及组] 校门外的树

原题链接:https://www.luogu.com.cn/problem/P1047

题意解读:0~l距离,每米一个点,包括两端,给定若干个区间,将区间内的点移除,最后剩下多个个点。

解题思路:

本题给出两种方法

1、本题数据规模不大,可以直接通过hash数组来处理

2、拓展一下,如果数据规模达到10^9,hash方法就不适用,可以采用区间合并

下面具体展开介绍。

方法1:hash

该法比较直接,设定int h[N],将所有区间中的点对应的h[i]设为1,最后统计h中还有多少0即可。

100分代码:

#include <bits/stdc++.h>
using namespace std;

int l, m, ans;
int h[100005];

int main()
{
    cin >> l >> m;
    int x, y;
    for(int i = 1; i <= m; i++)
    {
        cin >> x >> y;
        for(int j = x; j <= y; j++)
            h[j] = 1;
    }
    for(int i = 0; i <= l; i++) //从0开始,0也是有效位置
    {
        if(h[i] == 0) ans++;
    }
    cout << ans;

    return 0;
}

方法2:区间合并

由于多个区间有可能重叠,可以将所有区间进行合并,合并之后的区间没有重叠,然后用总数量减去所有区间覆盖的点数即可。

情况1:如上图所示,有三个区间[x1,y1],[x2,y2],[x3,y3],最终合并成[x1,y2],[x3,y3]两个区间,剩下的点数为L+1-(y3-x3+1)-(y2-x1+1)

情况2:如上图所示,有三个区间[x1,y1],[x2,y2],[x3,y3],最终合并成[x1,y1],[x3,y3]两个区间,剩下的点数为L+1-(y3-x3+1)-(y1-x1+1)

合并过程如下:

1、用结构体表示一个区间struct range{int x, y}

2、将所有区间按左端点从小到大排序

3、设定两个变量lastx,lasty表示上一个待保存的区间,初始设为第一个区间的左右端点

4、从第二区间开始枚举每一个区间,对于枚举到的区间,

  如果左端点大于lasty,表示开始了一个新的区间,将lastx,lasty区间保存到vector,更新lastx、lasty为当前区间

  如果左端点小于lasty,表示当前区间要和上一个区间合并,如果当前区间右端点更远则将lasty=当前区间的右端点

5、最后把剩下的lastx,lasty区间保存

具体过程可参考代码:

100分代码:

#include <bits/stdc++.h>
using namespace std;

int l, m, ans;
struct range
{
    int x, y;
};
vector<range> r1; //合并前的区间
vector<range> r2; //合并后的区间

bool cmp(range a, range b)
{
    return a.x < b.x;
}

int main()
{
    cin >> l >> m;
    int x, y;
    for(int i = 1; i <= m; i++)
    {
        cin >> x >> y;
        r1.push_back({x, y});
    }
    sort(r1.begin(), r1.end(), cmp);

    int lastx = r1[0].x, lasty = r1[0].y; //lastx,lasty为第一个区间
    for(int i = 1; i < r1.size(); i++) //从第二个区间开始枚举
    {
        if(r1[i].x > lasty) //左端点大于lasty,表示开始了一个新的区间
        {
            r2.push_back({lastx, lasty}); //将lastx,lasty区间保存
            lastx = r1[i].x, lasty = r1[i].y; //更新lastx,lasty为当前区间
        }
        else lasty = max(lasty, r1[i].y); //进行区间合并,如果当前区间右端点更远,将上一个区间右端点更新为当前区间右端点
    }
    r2.push_back({lastx, lasty}); //把剩下的lastx,lasty区间保存

    ans = l + 1;
    for(int i = 0; i < r2.size(); i++)
    {
        ans -= (r2[i].y - r2[i].x + 1);
    }
    cout << ans;

    return 0;
}

 

posted @ 2024-05-23 14:38  五月江城  阅读(28)  评论(0编辑  收藏  举报