游园安排 蓝桥杯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;
}