写出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 }
树套树:
树状数组套线段树:
注意线段树数组开足够大。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=100010; 4 int n,m,a[N],maxv[N],minv[N],maxn; 5 int root[N]; 6 inline int read(){ 7 int x=0,w=1;char c=0; 8 while(c<'0'||c>'9'){if(c=='-') w=-1;c=getchar();} 9 while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar(); 10 return x*w; 11 } 12 struct Segtree{ 13 int ls[N<<6],rs[N<<6],v[N<<6],tot; 14 inline void pushup(int k){ 15 v[k]=max(v[ls[k]],v[rs[k]]); 16 return; 17 } 18 int que(int k,int l,int r,int pos){ 19 if(!k) return 0; 20 if(l==r) return v[k]; 21 int mid=(l+r)>>1; 22 if(pos<=mid) return que(ls[k],l,mid,pos); 23 else return max(v[ls[k]],que(rs[k],mid+1,r,pos)); 24 } 25 void modify(int& k,int l,int r,int pos,int x){ 26 if(!k) k=++tot; 27 if(l==r){v[k]=max(v[k],x);return;} 28 int mid=(l+r)>>1; 29 if(pos<=mid) modify(ls[k],l,mid,pos,x); 30 else modify(rs[k],mid+1,r,pos,x); 31 pushup(k); 32 return; 33 } 34 }segtree; 35 struct Bit{ 36 inline int lowbit(int k){return k&(-k);} 37 int que(int bitpos,int segpos){ 38 int ans=0; 39 while(bitpos){ 40 ans=max(ans,segtree.que(root[bitpos],1,maxn,segpos)); 41 bitpos-=lowbit(bitpos); 42 } 43 return ans; 44 } 45 void modify(int bitpos,int segpos,int x){ 46 while(bitpos<=maxn){ 47 segtree.modify(root[bitpos],1,maxn,segpos,x); 48 bitpos+=lowbit(bitpos); 49 } 50 return; 51 } 52 }bit; 53 int main(){ 54 int t1,t2; 55 n=read(),m=read(); 56 for(int i=1;i<=n;i++) a[i]=minv[i]=maxv[i]=read(),maxn=max(maxn,a[i]); 57 while(m--){ 58 t1=read(),t2=read(); 59 maxn=max(maxn,t2); 60 minv[t1]=min(minv[t1],t2),maxv[t1]=max(maxv[t1],t2); 61 } 62 int d,ans; 63 for(int i=1;i<=n;i++){ 64 d=bit.que(a[i],minv[i])+1; 65 bit.modify(maxv[i],a[i],d); 66 ans=max(ans,d); 67 } 68 printf("%d",ans); 69 return 0; 70 }