值周 & 校门外的树

从暴力到差分/前缀和到离散化

暴力

在这里插入图片描述
这题因为数据规划只有1e5 和 100, 所以直接暴力遍历就可以解决.

//暴力方法
using namespace std;
#include<bits/stdc++.h>
int tree[10005];

int main(){
    int l,m;
    cin>>l>>m;
    int left,right;
    for(int i=0;i<=l;i++) tree[i]=1;
    for(int i=0;i<m;i++)
    {
        cin>>left>>right;
        for(int j=left;j<=right;j++) tree[j]--;
    }
    int sum=0;
    for(int i=0;i<=l;i++)
    {
        if(tree[i] == 1) sum++;
    }
    cout<<sum;
    return 0;
}
//差分方法
using namespace std;
#include<bits/stdc++.h>
const int maxn=1e5+5;
int a[maxn];

int main(){
    int l,m;
    cin>>l>>m;
    a[0]=1;
    for(int i=0;i<m;i++)
    {
        int x,y;
        cin>>x>>y;
        a[x]++;
        a[y+1]--;
    }
    int sum=0,tmp=0;
    for(int i=0;i<=l;i++)
    {
        tmp+=a[i];
        if(tmp == 1) sum++;
    }
    cout<<sum;
    return 0;
}

差分/前缀和

在这里插入图片描述
在这里插入图片描述
在这道题中,由于数据规模已经达到了1e8 和 1e6的级别,所以通过暴力的方式来做,复杂度会达到1e14的级别,必然会超时.但1e8的级别的int型数组依旧可以开,所以可以通过差分的方式来解决.
另外注意M已经达到1e6的级别了,如此大量的输入输出,如果直接用cin cout的话无疑会导致超时,所以这里需要用scanf printf.
关于遇到1则sum+1,可以参考下图解释.
在这里插入图片描述

using namespace std;
#include<bits/stdc++.h>
const int maxn=1e8+5;
int a[maxn];

int main(){
    int l,m;
    scanf("%d %d",&l,&m);
    int x,y;
    a[0]=1;//1'起始值为1,作为是否移走的标记
    for(int i=0;i<m;i++)
    {
        scanf("%d %d",&x,&y);
        a[x]++;
        a[y+1]--;//2'一定要是y+1,因为y这个点也被移走了
    }
    int sum=0,tmp=0;
    for(int i=0;i<=l;i++)//3'注意从0开始,以及<=l,l这个点也是包括在内的
    {
        tmp+=a[i];
        if(tmp == 1) sum++;
    }
    printf("%d",sum);
    return 0;
}

离散化

离散化是由于L的规模已经太大了,数组开不下去了才采用的.

//校门外的树
using namespace std;
#include<bits/stdc++.h>
const int maxn=1e5+5;
struct node{
    int pos,num;
}a[maxn];

bool cmp(node x,node y){
    return x.pos<y.pos;
}

int main(){
    int l,m;
    cin>>l>>m;
    for(int i=1;i<=m;i++)
    {
        int x,y;
        cin>>x>>y;
        a[2*i-1].pos=x;
        a[2*i-1].num=1;
        a[2*i].pos=y+1;
        a[2*i].num=-1;
    }
    sort(a+1,a+2*m+1,cmp);
    int sum=0,cnt=0;
    for(int i=1;i<=2*m;i++)
    {
        sum+=a[i].num;
        if(sum == 1 && a[i].num == 1)//从0变1的时候
        {
            cnt+=a[i].pos-a[i-1].pos;
        }
    }
    cnt+=l-a[2*m].pos+1;
    cout<<cnt;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值