校门外的树

https://ac.nowcoder.com/acm/contest/20960/1009
对数据范围较小的情况,直接暴力枚举即可。
或者利用差分的思想,先做差分,再做前缀和。

#include<bits/stdc++.h>
#define endl '\n'

using namespace std;

const int maxn = 1e4+3;
int det[maxn],prefix[maxn];

void solve()
{
    int l,n;
    cin>>l>>n;
    int x,y;
    while(n--)
    {
        cin>>x>>y;
        det[x]++;
        det[y+1]--;
    }
    int cnt=0,sum=0;
    for(int i=0;i<=l;i++)
    {
        sum+=det[i];
        if(sum==0) cnt++;
    }
    cout<<cnt<<endl;
}

int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int T; T=1;
    while(T--) solve();
    return 0;
}

https://ac.nowcoder.com/acm/contest/20960/1010
数据范围增大后,暴力行不通,这里有两种方法。
法1:记录下每个区间的左右端点,将区间按照左端点从小到大排序,枚举一遍区间,求出被拔走的树的数量,再用总的减去被拔走的即可。

#include<bits/stdc++.h>
#define endl '\n'
#define pii pair<int,int>

using namespace std;
const int maxn = 1e5+3;

struct Loc
{
    int x,y;
};

Loc a[maxn];

bool cmp(Loc x,Loc y)
{
    if(x.x==y.x) return x.y<y.y;
    else return x.x<y.x;
}

void solve()
{
    int l,n;
    cin>>l>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i].x>>a[i].y;
    }
    sort(a+1,a+1+n,cmp);
    int tempx=a[1].x;
    int tempy=a[1].y;
    int cnt=0;
    for(int i=2;i<=n;i++)
    {
        if(a[i].x>=tempx&&a[i].x<=tempy)
        {
            tempy=max(tempy,a[i].y);
        }
        else 
        {
            cnt+=tempy-tempx+1;
            tempx=a[i].x;
            tempy=a[i].y;
        }
    }
    cnt+=tempy-tempx+1;
    cout<<l+1-cnt<<endl;
}

int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int T; T=1;
    while(T--) solve();
    return 0;
}

法二:离散化,再利用差分的思想。

// 离散化解法
#include<bits/stdc++.h>
#define endl '\n'
#define pii pair<int,int>

using namespace std;

const int maxn = 2e5+3;

struct Loc
{
    int loc,num;
};

Loc a[maxn];

bool cmp(Loc x,Loc y)
{
    if(x.loc==y.loc) return x.num>y.num;
    else return x.loc<y.loc;
}

void solve()
{
    int l,n;
    cin>>l>>n;
    int x,y;
    for(int i=1;i<=n;i++)
    {
        cin>>x>>y;
        a[i].loc=x;
        a[i].num=1;
        a[i+n].loc=y;
        a[i+n].num=-1;
    }
    int sum=0;
    int ans=0;
    sort(a+1,a+1+2*n,cmp);
    ans+=a[1].loc;
    sum+=a[1].num;
    for(int i=2;i<=2*n;i++)
    {
        sum=sum+a[i].num;
        if(sum==1&&a[i].num==1)
        ans+=a[i].loc-a[i-1].loc-1;
    }
    ans+=l-a[2*n].loc;
    cout<<ans<<endl;
}

int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int T; T=1;
    while(T--) solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值