洛谷 p1020 LIS

157 阅读2分钟

LIS和LCS

LIS 模板

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int arr[100000+10],n;
vector<int> vs;

/*
   lis问题模板,使用二分+贪心
   if(arr[i]>arr[i-1])
      vector.push(arr[i])
   else
      vector中大于arr[i]的最小的数变成arr[i]
*/
int main(){
   freopen("data.in","r",stdin);
   cin>>n;
   for(int i=1;i<=n;i++)
      cin>>arr[i];
   vs.push_back(arr[1]);
   int ind;
   for(int i=2;i<=n;i++){
      if(arr[i]>vs.back()){
         vs.push_back(arr[i]);
      }else{
         ind = lower_bound(vs.begin(),vs.end(),arr[i])-vs.begin();
         vs[ind] = arr[i];
      }
   }
   // vs的长度就是最长上升子序列的长度
   for(int i=0;i<vs.size();i++)
      cout<<vs[i]<<" ";
   return 0;
}

1020 导弹拦截

  1. 思路:

    1. 本题要求两个东西,第一个很明显就是最长不下降子序列,第二问在不知道的情况下很难想到是最长上升子序列...
    2. 这次借鉴(照抄)的是w1049344862的写法,巧妙的使用lower_bound和upper_bound使得最长上升子序列和最长下降子序列变得异常简单
  2. 重点

    1. lower_bound会查找第一个大于等于要找的数,而upper_bound是大于要找的数的数

          int arr[10] = {1,2,3,4,5,6,7,8,9,10};
          int ind1 = lower_bound(arr,arr+10,3)-arr;
          cout<<ind1<<endl;
          int ind2 = upper_bound(arr,arr+10,3)-arr;
          cout<<ind2;
      // 输出 2 3
      
    2. 最奇技淫巧的地方:使用greater()来让upper_bound变成求第一个小于要找的数

    3. 也就是说,LIS的模板只需要少量代码修改就能变成求LCS

            if(arr[i]<=vs.back()){
               vs.push_back(arr[i]);
            }else{
               ind = upper_bound(vs.begin(),vs.end(),arr[i])-vs.begin();
               vs[ind] = arr[i];
            }
      

      只能说大佬666

ac代码

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int arr[100000+10],n;
vector<int> vs1,vs2;

int main(){
   freopen("data.in","r",stdin);
   while(cin>>arr[n]){
      n++;
   }
   vs1.push_back(arr[0]);
   vs2.push_back(arr[0]);
   int ind;
   for(int i=1;i<n;i++){
      // 最长上升子序列
      if(arr[i]>vs1.back()){
         vs1.push_back(arr[i]);
      }else{
         ind = lower_bound(vs1.begin(),vs1.end(),arr[i])-vs1.begin();
         vs1[ind] = arr[i];
      }
      if(arr[i]<=vs2.back()){
         vs2.push_back(arr[i]);
      }else{
         ind = upper_bound(vs2.begin(),vs2.end(),arr[i],greater<int>())-vs2.begin();
         vs2[ind] = arr[i];
      }
   }
   cout<<vs2.size()<<endl<<vs1.size();
   return 0;
}