写出dp方程,可以发现转移要满足一个三维偏序,那么可以处理三维偏序的方法优化。
CDQ分治:
cdq分治和树状数组是好伙伴~
注意分治的顺序,要保证先求解出所有前驱状态。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=100010; 4 int n,m,dp[N],maxn; 5 struct Node{ 6 int a,maxv,minv,id; 7 }node[N]; 8 int cmpa(const Node& x,const Node& y){return x.a<y.a;} 9 int cmpv(const Node& x,const Node& y){return x.maxv<y.maxv;} 10 int cmpid(const Node& x,const Node& y){return x.id<y.id;} 11 int bit[N]; 12 inline int lowbit(int k){return k&(-k);} 13 inline void change(int k,int x){while(k<=maxn) bit[k]=max(bit[k],x),k+=lowbit(k);return;} 14 inline int que(int k){ 15 int ans=0; 16 while(k) ans=max(bit[k],ans),k-=lowbit(k); 17 return ans; 18 } 19 inline void reset(int k){ 20 while(k<=maxn){ 21 if(!bit[k]) return; 22 bit[k]=0,k+=lowbit(k); 23 } 24 return; 25 } 26 void cdq(int l,int r){ 27 if(l>=r) return; 28 int mid=(l+r)>>1; 29 cdq(l,mid); 30 sort(node+l,node+mid+1,cmpv);sort(node+mid+1,node+r+1,cmpa); 31 int pl=l,pr=mid+1; 32 while(pl<=mid&&pr<=r){ 33 if(node[pl].maxv<=node[pr].a){ 34 change(node[pl].a,dp[node[pl].id]); 35 pl++; 36 }else{ 37 dp[node[pr].id]=max(dp[node[pr].id],que(node[pr].minv)+1); 38 pr++; 39 } 40 } 41 while(pr<=r){ 42 dp[node[pr].id]=max(dp[node[pr].id],que(node[pr].minv)+1); 43 pr++; 44 } 45 for(int i=l;i<=mid;i++) reset(node[i].a); 46 sort(node+l,node+r+1,cmpid); 47 cdq(mid+1,r); 48 return; 49 } 50 int main(){ 51 int t1,t2; 52 scanf("%d%d",&n,&m); 53 for(int i=1;i<=n;i++) scanf("%d",&node[i].a),node[i].maxv=node[i].minv=node[i].a,node[i].id=i,dp[i]=1,maxn=max(maxn,node[i].a); 54 while(m--){ 55 scanf("%d%d",&t1,&t2); 56 maxn=max(maxn,t2); 57 node[t1].maxv=max(node[t1].maxv,t2); 58 node[t1].minv=min(node[t1].minv,t2); 59 } 60 cdq(1,n); 61 int ans=0; 62 for(int i=1;i<=n;i++) ans=max(ans,dp[i]); 63 printf("%d",ans); 64 return 0; 65 }