洛谷 P3740 [HAOI2014]贴海报

洛谷 P3740 [HAOI2014]贴海报

Description

  • Bytetown城市要进行市长竞选,所有的选民可以畅所欲言地对竞选市长的候选人发表言论。为了统一管理,城市委员会为选民准备了一个张贴海报的electoral墙。

    张贴规则如下:

    1. electoral墙是一个长度为N个单位的长方形,每个单位记为一个格子;
    2. 所有张贴的海报的高度必须与electoral墙的高度一致的;
    3. 每张海报以“A B”表示,即从第A个格子到第B个格子张贴海报;
    4. 后贴的海报可以覆盖前面已贴的海报或部分海报。

    现在请你判断,张贴完所有海报后,在electoral墙上还可以看见多少张海报。

Input

  • 第一行: N M 分别表示electoral墙的长度和海报个数

    接下来M行: Ai Bi 表示每张海报张贴的位置

Output

  • 输出贴完所有海报后,在electoral墙上还可以看见的海报数。

Sample Input

100 5
1 4
2 6
8 10
3 4
7 10

Sample output

4

题解:

  • 看完题。我心里冒出了很多个想法:线段树?排序比较?暴力?
  • 思来想去看到m<=1000,暴力无疑了。离散化不就行了!?
  • 记住,离散化的特征:离散的元素个数少,元素数据范围贼大
  • 所以离散化后暴力查找就行了。
  • 但离散化也有坑:
    • 假如现在有这么一个数据:
    • 1 10
    • 1 4
    • 7 10
    • 离散化后:1 –> 1;4 –> 2;7 –> 3;10 –> 4
    • 离散化后的区间:
    • 1 4
    • 1 2
    • 2 3
    • 那第一个区间不就被覆盖掉了吗!!
    • 其实是没有的!
  • 那如何避免这种情况?你把a[i].l和a[i].r加入离散化数组了对吧,那同时将a[i].r + 1也加入离散化数组。这样就保证了每个区间后面有一块“预留的位置”,从而不会出现中间的部分没有了这种情况
#include <iostream>
#include <cstdio>
#include <algorithm>
#define maxm 1005
using namespace std;

struct A {int l, r;} a[maxm];
int n, m, cnt, ans;
int b[maxm * 2], c[maxm * 2];
bool vis[maxm * 2];

int find(int x) {
    return lower_bound(b + 1, b + 1 + cnt, x) - b;
}

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= m; i++)
    {
        cin >> a[i].l >> a[i].r;
        b[++cnt] = a[i].l, b[++cnt] = a[i].r, b[++cnt] = a[i].r + 1;
        //为什么要加a[i].r + 1  ??
        //因为中间的部分没有了,比如[1,4]和[7,10]覆盖在[1,10]上面的话,查的时候离散化的数组
        //里面只有1 4 7 10,中间[5,6]还有别的海报就没有了,所以把r+1也加到离散化的数组里,
        //这样的话加入[1,4]的时候会把5加进去,就不会导致4后面还有海报而查不到的情况
    }
    sort(b + 1, b + 1 + cnt);
    cnt = unique(b + 1, b + 1 + cnt) - b - 1;
    for(int i = 1; i <= m; i++)
        for(int j = find(a[i].l); j <= find(a[i].r); j++)
            c[j] = i;
    vis[0] = 1;
    for(int i = 1; i <= cnt; i++)
        if(!vis[c[i]]) ans++, vis[c[i]] = 1;
    cout << ans;
    return 0;
}

转载于:https://www.cnblogs.com/BigYellowDog/p/11161094.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值