题意

给你个区间

选出最少长度的序列,满足按序列顺序操作,每次对

的元素进行排序

最后在位置的数需要是最大的数(你必须保证对于任意的元素顺序,都满足这点)

分析

非常经典的题

很容易想到当最大的数在位置时如果都能满足条件,任意情况都能满足条件

于是定义表示当前覆盖了的最小区间个数

转移从里找最小值就好了

用线段树优化找最小值的过程即可

#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
using namespace std;
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (l+r>>1)
#define lson ls,l,mid
#define rson rs,mid+1,r
const int maxn=5e6+10;
const int inf=1e9;
int n,m,dp[maxn],l[maxn],r[maxn],a[maxn],maxx[maxn];
void build(int rt,int l,int r)
{
    if( l==r ){ a[rt]=maxx[rt]=dp[l]; return; }
    build(lson); build(rson);
    maxx[rt] = min( maxx[ls],maxx[rs] );
}
void insert(int rt,int l,int r,int u)
{
    if( l==r&&l==u ){ a[rt]=maxx[rt]=dp[u]; return; }
    if( r<u||l>u )    return;
    insert(lson,u); insert(rson,u);
    maxx[rt] = min( maxx[ls],maxx[rs] );
}
int query(int rt,int l,int r,int L,int R)
{
    if( l>=L&&r<=R )    return maxx[rt];
    if( l>R||r<L )    return inf;
    return min( query(lson,L,R),query(rson,L,R) );
}
int main()
{
    cin >> n >> m;
    for(int i=1;i<=m;i++)
        scanf("%d%d",&l[i],&r[i]);
    dp[1]=0;
    for(int i=1;i<=n;i++)    dp[i]=inf;
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        dp[r[i]] = min( dp[r[i]],query(1,1,n,l[i],r[i] )+1 );
        insert( 1,1,n,r[i] );
    }
    cout << dp[n];
}