P2082 区间覆盖(加强版)(贪心)

地址:https://www.luogu.com.cn/problem/P2082

解析:

刚开始自己写的代码:

我对L递增排列,L相等按R递增排列。

直接逐个判断,相交,或者不相交。

但让每一个区间只和它前一个区间发生关系,显然是错误的。

比如:

[1,5]

[2,4]

[3,6]

答案应该是6,但是我这个代码输出的是7,原因是第三个区间[3,6]与[2,4]发生了关系,但是[1,5]已经把[2,4]覆盖了。

#include<cstdio>//WAWAWAWAWAWA!
#include<stack>
#include<map>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+20;
struct node
{
    ll l,r;
}st[maxn];
bool cmp(node a , node b)
{
    if(a.l==b.l)
        return a.r<b.r;
    return a.l<b.l;
}
int main()
{    // 4 0 20
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>st[i].l>>st[i].r;
    }
    ll sum=0;
    sort(st+1,st+1+n,cmp);
    sum=st[1].r-st[1].l+1;
    for(int i=2;i<=n;i++)
    {
        if(st[i].r>st[i-1].r)
        {
            if(st[i].l>st[i-1].r)
                sum+=st[i].r-st[i].l+1;
            else
                sum+=st[i].r-st[i-1].r;
        }
    }
    cout<<sum<<endl;
}

正确的贪心思路:

因为首要排序的是L,所以这个情况下R基本是乱序的。

下一个区间需要算的前提是什么?当然是超出之前所有区间的范围了。

所以可以维护一个最大r,只有当前的区间超越r,才能纳入计算(其实自己算也是这个思想的,脑袋秀逗了)。

同时更新最大的r。
引以为戒~

AC代码:

#include<cstdio>
#include<stack>
#include<map>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+20;
struct node
{
    ll l,r;
}st[maxn];
bool cmp(node a , node b)
{
    if(a.l==b.l)
        return a.r<b.r;
    return a.l<b.l;
}
int main()
{    // 4 0 20
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>st[i].l>>st[i].r;
    }
    ll sum=0;
    sort(st+1,st+1+n,cmp);
    sum=st[1].r-st[1].l+1;
    ll r=st[1].r;
    for(int i=2;i<=n;i++)
    {
        if(st[i].l>r)
        {
            sum+=st[i].r-st[i].l+1;
            r=st[i].r;
        }
        else if(st[i].r>r)
        {
            sum+=st[i].r-r;
        }
        r=max(r,st[i].r);
    }
    cout<<sum<<endl;
}

 

posted @ 2020-07-08 17:17  liyexin  阅读(294)  评论(0编辑  收藏  举报