记第i个位置有三个属性:1.ai表示原来的值;2.bi表示变成最大的值;3.ci表示变成最小的值。那么对于如果i在j的前面,那么必然有:$ai\le cj$且$bi\le aj$,那么令f[i]表示以i为结尾的最长上升子序列,即对求max(f[j])满足j能在i的前面,用树套树维护即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 #define mid (l+r>>1) 5 int V,n,m,x,y,ans,a[N],b[N],c[N],ro[N*200],f[N*200],ls[N*200],rs[N*200]; 6 void update(int &k,int l,int r,int x,int y,int z){ 7 if (!k)k=++V; 8 if (y)update(ro[k],1,N-5,y,0,z); 9 if (l==r){ 10 f[k]=max(f[k],z); 11 return; 12 } 13 if (x<=mid)update(ls[k],l,mid,x,y,z); 14 else update(rs[k],mid+1,r,x,y,z); 15 f[k]=max(f[ls[k]],f[rs[k]]); 16 } 17 int query(int k,int l,int r,int x,int y,int x2,int y2){ 18 if ((!k)||(l>y)||(x>r))return 0; 19 if ((x<=l)&&(r<=y)) 20 if (x2)return query(ro[k],1,N-5,x2,y2,0,0); 21 else return f[k]; 22 return max(query(ls[k],l,mid,x,y,x2,y2),query(rs[k],mid+1,r,x,y,x2,y2)); 23 } 24 int main(){ 25 scanf("%d%d",&n,&m); 26 for(int i=1;i<=n;i++){ 27 scanf("%d",&a[i]); 28 b[i]=c[i]=a[i]; 29 } 30 for(int i=1;i<=m;i++){ 31 scanf("%d%d",&x,&y); 32 b[x]=max(b[x],y); 33 c[x]=min(c[x],y); 34 } 35 update(x=0,1,N-5,a[1],b[1],1); 36 for(int i=2;i<=n;i++){ 37 int s=query(1,1,N-5,1,c[i],1,a[i])+1; 38 update(x,1,N-5,a[i],b[i],s); 39 ans=max(ans,s); 40 } 41 printf("%d\n",ans); 42 }