题意
给你个区间
选出最少长度的序列,满足按序列顺序操作,每次对
的元素进行排序
最后在位置的数需要是最大的数(你必须保证对于任意的元素顺序,都满足这点)
分析
非常经典的题
很容易想到当最大的数在位置时如果都能满足条件,任意情况都能满足条件
于是定义表示当前覆盖了
的最小区间个数
转移从里找最小值就好了
用线段树优化找最小值的过程即可
#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];
}
京公网安备 11010502036488号