E04 二分+贪心 B3637 最长上升子序列
E04 线性DP 最长上升子序列 二分优化_哔哩哔哩_bilibili
// 二分+贪心 O(nlogn) #include<bits/stdc++.h> using namespace std; const int N=100010; int n,a[N]; int len,b[N]; //记录上升子序列 int main(){ scanf("%d",&n); for(int i=1; i<=n; i++) scanf("%d",&a[i]); b[0]=-2e9; //哨兵 for(int i=1; i<=n; i++) if(b[len]<a[i]) b[++len]=a[i]; //a[i]大于队尾数,则插入队尾 else *lower_bound(b+1,b+len+1,a[i])=a[i]; //用a[i]替换第一个大于等于它的数 printf("%d\n",len); }
// 二分+贪心 O(nlogn) #include<bits/stdc++.h> using namespace std; const int N=100010; int n,a[N]; int len,b[N]; //记录上升子序列 int pos[N],ans[N]; //pos[i]=j 表示a[i]排在b序列中的j位置 int main(){ scanf("%d",&n); for(int i=1; i<=n; i++) scanf("%d",&a[i]); b[0]=-2e9; //哨兵 for(int i=1; i<=n; i++){ if(b[len]<a[i]){ b[++len]=a[i]; pos[i]=len; // printf("%d %d\n",a[i],len); } else{ int m=lower_bound(b+1,b+len+1,a[i])-b; b[m]=a[i]; pos[i]=m; // printf("%d %d:\n",a[i],m); } } for(int i=n,j=len; i>=1&&j; i--){ if(pos[i]==j) ans[j--]=a[i]; } for(int i=1; i<=len; i++) printf("%d ",ans[i]); }