做法:线段树优化dp

思路:

dp[i]表示覆盖[1,i]需要的最少区间数。然后用线段树更新取最小值。
dp[t]=min(dp[t],min(dp[s]~dp[t])+1)

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=5e4+10,INF=0x3f3f3f3f;

int n,m;
int dp[N<<2];

int query(int u,int l,int r,int x,int y){
    if(l>=x&&r<=y) return dp[u];
    int mid=(l+r)>>1,sum=INF;
    if(x<=mid) sum=query(u<<1,l,mid,x,y);
    if(y>=mid+1) sum=min(sum,query(u<<1|1,mid+1,r,x,y));
    return sum;
}

void modify(int u,int l,int r,int x,int y){
    if(l==r) dp[u]=min(dp[u],y);
    else{
        int mid=(l+r)>>1;
        if(x<=mid) modify(u<<1,l,mid,x,y); 
        else if(x>=mid+1) modify(u<<1|1,mid+1,r,x,y);

        dp[u]=min(dp[u<<1],dp[u<<1|1]);
    }
}

int main(){
    ios_base::sync_with_stdio(false);cin.tie(0);
    memset(dp,INF,sizeof dp);
    cin>>n>>m;
    modify(1,1,n,1,0);
    for(int i=0;i<m;i++){
        int s,t;cin>>s>>t;
        int temp=query(1,1,n,s,t)+1;
        modify(1,1,n,t,temp);
    }
    cout<<query(1,1,n,n,n)<<"\n";
    return 0;
}