蓝桥杯 算法提高 线段和点

算法提高 线段和点
时间限制:1.0s 内存限制:256.0MB
提交此题
问题描述
  有n个点和m个区间,点和区间的端点全部是整数,对于点a和区间[b,c],若a>=b且a<=c,称点a满足区间[b,c]。
  求最小的点的子集,使得所有区间都被满足。
输入格式
  第一行两个整数n m
  以下n行 每行一个整数,代表点的坐标
  以下m行 每行两个整数,代表区间的范围
输出格式
  输出一行,最少的满足所有区间的点数,如无解输出-1。
样例输入
5 5
2
6
3
8
7
2 5
3 4
3 3
2 7
6 9
样例输出
2
数据规模和约定
  1<=n,m<=10000
  0<=点和区间的坐标<=50000

http://lx.lanqiao.cn/problem.page?gpid=T367

首先将区间起点按照从小到大排序 然后终点也是按照从小到大排序
用一个cmp实现。
之后 用l 和 r 记录 区间叠加的时候的重复区间的大小

用队列记录符合l和r的点的个数
当队列里所有元素都不符合l和r 的时候 那么 就是证明这个新的区间和上面的区间没有重复可用的点了。
这个时候就让点数加1即可
最后 定义两个极限大的哨兵,起到记录最后一个点的情况。

#include<bits/stdc++.h>
using namespace std;
int a[10005];//点
queue<int > tag;//记录符合l,r的点的集合。
struct se//区间
{
    int x,y;
}d[10005];
bool cmp(se a,se b)
{
    if(a.x!=b.x) return a.x<b.x;
    return a.y<b.y;
}
int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        for(int i=0;i<n;i++) cin>>a[i];

        for(int i=0;i<m;i++)
            cin>>d[i].x>>d[i].y;


        sort(d,d+m,cmp);

       // for(int i=0;i<n;i++) cout<<a[i]<<' '; cout<<endl;
       // for(int i=0;i<m;i++) cout<<d[i].x<<' '<<d[i].y<<' '<<"zzz"<<endl;
        int z=1,j=0,sum=0,l,r;
        d[m].x=1000000000,d[m].y=1000000000;
        for(int i=0;i<=m;i++)
        {
            if(d[i].x>l) l=d[i].x;
            if(d[i].y<r) r=d[i].y;
            if(tag.size()&&(l>tag.front()||r<tag.front()))
            {
                while(tag.size()&&(l>tag.front()||r<tag.front()))
                {
                    //cout<<tag.front()<<"  ci"<< ' '<<d[i].x<<' '<<d[i].y<<endl;
                    tag.pop();
                    if(tag.size()==0)
                    {
                        sum++;
                        z=1;
                        break;
                    }
                }
            }
            if(z)
            {
                l=d[i].x;
                r=d[i].y;
                for(j=0;j<n;j++)
                    if(a[j]>=d[i].x&&a[j]<=d[i].y)
                        tag.push(a[j]);

                z=0;
               // cout<<d[i].x<<' '<<d[i].y<< ' '<<"tag"<<endl;
                //cout<<j<<' '<<"  s"<<' '<<tag.front()<<' '<<tag.back()<<endl;
            }
        }
        //cout<<sum<<endl;
       // cout<<tag.size()<<endl;
        if(!sum) cout<<"-1"<<endl;
        else cout<<sum<<endl;
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值