设f[i]是以i位置为结尾的最长满足条件子序列的长度
那么j能转移到i的条件是,$j<i , max[j]<=a[i] , a[j]<=min[i]$,其中max和min表示这个位置能变化出来的最大值或最小值
这个东西用一个cdq来做
具体来说,先做左半区间,然后左边按max排序,右边按a排序,把左边的f按a为下标加到树状数组里,右面的用min来查,最后在做右半区间
#include<bits/stdc++.h>
#define CLR(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pa;
const int maxn=1e5+; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N,M,V=1e5,a[maxn],ma[maxn],mi[maxn],f[maxn],ord[maxn]; inline bool cmp1(int x,int y){return a[x]<a[y];}
inline bool cmp2(int x,int y){return mi[x]<mi[y];} int tr[maxn];
inline int lowbit(int x){return x&(-x);}
inline void change(int x,int y){
for(;x<=V;x+=lowbit(x)) tr[x]=y?max(tr[x],y):;
}
inline int query(int x){
int re=;for(;x;x-=lowbit(x)) re=max(re,tr[x]);return re;
} inline void cdq(int l,int r){
if(l>=r) return;
int m=l+r>>;
cdq(l,m);
for(int i=l;i<=r;i++) ord[i]=i;
sort(ord+l,ord+m+,cmp1),sort(ord+m+,ord+r+,cmp2);
int p=l,q=m+;
for(;q<=r;q++){
for(;p<=m&&a[ord[p]]<=mi[ord[q]];p++) change(ma[ord[p]],f[ord[p]]);
f[ord[q]]=max(f[ord[q]],query(a[ord[q]])+);
}
for(p=l;p<=m;p++) change(ma[ord[p]],);
cdq(m+,r);
} int main(){
//freopen("","r",stdin);
int i,j,k;
N=rd(),M=rd();
for(i=;i<=N;i++)
a[i]=ma[i]=mi[i]=rd(),f[i]=;
for(i=;i<=M;i++){
int x=rd(),y=rd();
ma[x]=max(ma[x],y),mi[x]=min(mi[x],y);
}
cdq(,N);
int ans=;
for(i=;i<=N;i++) ans=max(ans,f[i]);
printf("%d\n",ans);
return ;
}