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; } else{ int j=lower_bound(b+1,b+len+1,a[i])-b; b[j]=a[i]; pos[i]=j; //若无后续更长序列,此记录无效,因len在i之前 } } 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]); }
浙公网安备 33010602011771号