WA*21 求救
查看原帖
WA*21 求救
482610
Mortidesperatslav楼主2025/7/21 22:41

做法:二分 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;
}
2025/7/21 22:41
加载中...