做法:二分 LCP,然后算出前半部分最多可以贡献多少段,贪心查询。
#include<bits/stdc++.h>
using namespace std;
int n, k, a[200005], pos[200005], f[200005], s[200005], tg[200005], siz;
int tr[200005];
priority_queue<int, vector<int>, greater<int> > Q;
priority_queue<int> Q2;
int lowbit(int x){
return x & (-x);
}
void upd(int u, int x){
for (; u <= n; u += lowbit(u))
tr[u] += x;
}
int qry(int u){
int ans = 0;
for (; u; u -= lowbit(u))
ans += tr[u];
return ans;
}
int check(int mid){
for (int i = 1; i <= n; i++)
tr[i] = 0;
for (int i = mid + 1; i <= n; i++)
upd(a[i], 1);
int mx = 0;
for (int i = 1; i <= mid; i++){
if (a[i] > a[1])
continue;
int ans = qry(a[i]);
// cout << i << " " << ans << " " << f[i] << "\n";
if (!ans)
continue;
if (ans + f[i] >= k)
mx = max(mx, f[i]);
}
return mx;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n >> k;
for (int i = 1; i <= n; i++){
cin >> a[i];
pos[a[i]] = i;
}
if (a[1] <= k){
for (int i = k; i >= 1; i--)
for (int j = pos[i]; ; j++){
if (a[j] <= k && a[j] != i)
break;
cout << a[j] << " ";
}
return 0;
}
for (int i = 1; i <= n; i++){
int l = 1, r = siz, pos = siz + 1;
while (l <= r){
int mid = (l + r) >> 1;
if (s[mid] < a[i])
pos = mid, r = mid - 1;
else
l = mid + 1;
}
if (pos > siz)
++siz;
s[pos] = a[i];
f[i] = pos;
}
int l = 1, r = n, ans = 0, mx = 0;
while (l <= r){
int mid = (l + r) >> 1;
if (check(mid))
ans = mid, l = mid + 1;
else
r = mid - 1;
}
mx = check(ans);
// cout << ans << " " << mx << "\n";
for (int i = 1; i <= ans; i++)
cout << a[i] << " ";
for (int i = ans + 1; i <= n; i++)
Q.push(a[i]);
for (int i = 1; i <= k - mx; i++){
Q2.push(Q.top());
tg[pos[Q.top()]] = 1;
Q.pop();
}
for (int i = 1; i <= k - mx; i++){
int qwq = Q2.top();
Q2.pop();
for (int j = pos[qwq]; j <= n && !(j != pos[qwq] && tg[j]); j++)
cout << a[j] << " ";
}
return 0;
}