游园安排【蓝桥杯第十一届】【决赛】【A组】(最长上升子序列(贪心,二分搜索)+输出)

题目:“蓝桥杯”练习系统 (lanqiao.cn)

思路:

  • 就是求最大的上升子序列(字母字典序版本,直接比较就行了,系统自动排)
  • 思路: 维护一个严格上升的子序列,让里面的元素尽量小,
  • 既 一个新来的东西, 大于最大值,就排在末尾,然后就在子序列里找到第一个大于等于的这个数(为什么要大于等于,因为是要严格上升),然后把他替换掉
  • 找的时候用 lower_bound 就行了, 是一种贪心的思想,我不好解释 qwq
  • 输出的时候也是一种贪心的思想, 逆序找,看他这个字符 的 size 是不是 当前的size,是 就代表他是最小的,且符合题意的,应为在后面的字符还能更新那么他一定是比前面小于或者等于的,就看他的size是不是符合!!
#include <bits/stdc++.h>
using namespace std;
#define ri register int
#define M 1000005

int n,m;
string p[M];
string q[M];
int num[M];
string ans[M];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    string s;
    cin>>s;
    string tmp;
    for(ri i=0;i<s.length();i++)
    {
       if(s[i]>='A'&&s[i]<='Z'&&i!=0)
       {
             p[++n]=tmp;tmp=s[i];continue;
       }
       tmp+=s[i];
    }
    p[++n]=tmp;
    int r=1;
    q[r]=p[1];
    num[r]=1;
    for(ri i=2;i<=n;i++)
    {
        if(p[i]>q[r])
        {
            q[++r]=p[i];
             num[i]=r;
        }
        else
        {
            int a=lower_bound(q+1,q+1+r,p[i])-q;
            q[a]=p[i];
            num[i]=a;
        }
    }
    for(ri i=n,j=r;i>=1;i--)
    {
        if(num[i]==j)
        {
            ans[j]=p[i];
            j--;
        }
    }
    for(ri i=1;i<=r;i++)
    {
        cout<<ans[i];
    }
    return 0;
}
View Code

 

posted @ 2022-06-14 18:55  VxiaohuanV  阅读(43)  评论(0)    收藏  举报