E04 二分+贪心 B3637 最长上升子序列

E04 线性DP 最长上升子序列 二分优化_哔哩哔哩_bilibili

 

 B3637 最长上升子序列 - 洛谷

// 二分+贪心 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);
}

 

T386911 最长上升子序列输出解 - 洛谷

// 二分+贪心 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]);
}

 

U245788 最长上升子序列 - 洛谷

 

posted @ 2023-04-09 22:25  董晓  阅读(1161)  评论(1)    收藏  举报