游园安排 蓝桥杯2020 G题

原题链接
考察:线性dp
思路:
  二分求最长上升子序列板子题,我们可以发现二分求得的最长上升队列中,保存的就是当前长度最小的数字,因此我们只需要每覆盖一个存储它们前面一个,最后递归输出.

Code

#include <iostream> 
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1000010;
string A[N],s,ans;
int cnt,q[N],pre[N];
void dfs(int u)
{
    if(!u) return;
    dfs(pre[u]);
    ans+=A[u];
}
void init()
{
    int len = s.size();
    for(int i=0,j=0;i<len;i++)
    {
        if(s[i]>='A'&&s[i]<='Z')
        { 
            j = i;
            while(j+1<len&&s[j+1]>='a'&&s[j+1]<='z') j++;
            A[++cnt] = s.substr(i,j-i+1);
            i = j;
        }
    }
}
void solve()
{
    int len = 0;
    for(int i=1;i<=cnt;i++)
    {
        int l = 0,r = len;
        while(l<r)
        {
            int mid = l+r+1>>1;
            if(A[q[mid]]<A[i]) l = mid;
            else r = mid-1; 
        }
        q[r+1] = i;
        pre[i] = q[r];
        len = max(r+1,len);
    }
    int idx = q[len];
    dfs(idx);
    cout<<ans<<endl;
}
int main()
{
    cin>>s;
    init();
    solve();
    return 0;
}
posted @ 2021-06-04 19:18  acmloser  阅读(121)  评论(0编辑  收藏  举报