设一个位置的数的最大可能值为
m
x
mx
mx,最小为
m
n
mn
mn,原本值为
v
a
l
val
val
DP时显然需要满足以下条件:
j
<
i
j<i
j<i
v
a
l
j
<
m
n
i
val_j<mn_i
valj<mni
m
x
j
<
v
a
l
i
mx_j<val_i
mxj<vali
显然三维偏序,CDQ+树状数组
Code:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
inline void chkmx(int &x,int y){x=x>y?x:y;}
inline void chkmn(int &x,int y){x=x<y?x:y;}
const int N=1e5+5;
int Mx=0;
struct info{
int mn,mx,val,id,ans;
}q[N];
inline bool cmp1(const info &a,const info &b){return a.id<b.id;}
inline bool cmp2(const info &a,const info &b){return a.val<b.val;}
inline bool cmp3(const info &a,const info &b){return a.mn<b.mn;}
namespace CDQ{
int tr[N];
inline int lb(int x){return x&(-x);}
inline void add(int x,int y){for(int i=x;i<=Mx;i+=lb(i)) chkmx(tr[i],y);}
inline void clear(int x){for(int i=x;i<=Mx;i+=lb(i)) tr[i]=0;}
inline int ask(int x){int res=0;for(int i=x;i;i-=lb(i)) chkmx(res,tr[i]);return res;}
void solve(int l,int r){
if(l==r) return;
int mid=l+r>>1;
solve(l,mid);
sort(q+l,q+mid+1,cmp2);sort(q+mid+1,q+r+1,cmp3);
int i=l,j=mid+1;
while(i<=mid && j<=r){
if(q[i].val<=q[j].mn){add(q[i].mx,q[i].ans);++i;}
else{chkmx(q[j].ans,ask(q[j].val)+1);++j;}
}
while(j<=r) {chkmx(q[j].ans,ask(q[j].val)+1);++j;}
for(int k=l;k<i;k++) clear(q[k].mx);
sort(q+mid+1,q+r+1,cmp1);solve(mid+1,r);
}
}
using CDQ::solve;
int main(){
int n=read(),m=read();
for(int i=1;i<=n;i++){
int x=read();
q[i].val=q[i].mn=q[i].mx=x;q[i].ans=1;q[i].id=i;chkmx(Mx,x);
}
for(int i=1;i<=m;i++){
int pos=read(),val=read();
chkmx(q[pos].mx,val);chkmn(q[pos].mn,val);chkmx(Mx,val);
}
solve(1,n);
int ans=0;
for(int i=1;i<=n;i++) chkmx(ans,q[i].ans);
cout<<ans;
return 0;
}