[ABC262F] Erase and Rotate

Problem Statement

You are given a sequence $P = (p_1,p_2,\ldots,p_N)$ that contains $1,2,\ldots,N$ exactly once each.
You may perform the following operations between $0$ and $K$ times in total in any order:

  • Choose one term of $P$ and remove it.
  • Move the last term of $P$ to the head.

Find the lexicographically smallest $P$ that can be obtained as a result of the operations.

Constraints

  • $1 \leq N \leq 2 \times 10^5$
  • $0 \leq K \leq N-1$
  • $1 \leq p_i \leq N$
  • $(p_1,p_2,\ldots,p_N)$ contains $1,2,\ldots,N$ exactly once each.
  • All values in input are integers.

Input

Input is given from Standard Input in the following format:

$N$ $K$
$p_1$ $p_2$ $\ldots$ $p_N$

Output

Print the lexicographically smallest $P$ that can be obtained as a result of the operations, separated by spaces.


Sample Input 1

5 3
4 5 2 3 1

Sample Output 1

1 2 3

The following operations make $P$ equal $(1,2,3)$.

  • Removing the first term makes $P$ equal $(5,2,3,1)$.
  • Moving the last term to the head makes $P$ equal $(1,5,2,3)$.
  • Removing the second term makes $P$ equal $(1,2,3)$.

There is no way to obtain $P$ lexicographically smaller than $(1,2,3)$, so this is the answer.


Sample Input 2

3 0
3 2 1

Sample Output 2

3 2 1

You may be unable to perform operations.


Sample Input 3

15 10
12 10 7 2 8 11 9 1 6 14 3 15 13 5 4
思路不算特别难,但超多细节。建议拿正确代码对拍。

考虑直接贪心。首先第一位要尽量小。我们可以从前 \(k+1\) 个数中选,亦可以从倒数 \(k\) 个中选。如果从倒数 \(k\) 个选,我们可以直接把后面 \(k\) 个中最小的转到前面。如果从前 \(k+1\) 个选,我们就把最小的那位的前面删掉就可以了。

假设我们现在确定了第一位,那么后面我们可以用类似单调栈的方法维护最小字典序字符串。就可以了。单调栈删元素的时候要特判,当某一位是从后面转过来的时候,我们可以把转的那一步改为删除。所以不消耗次数。

不知道赛时怎么写出来这一题。

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
int n,k,a[N],st[N],j,q[N],l=2e5,r=2e5-1,t[N],ret,tp,p,g,f[N];
int main()
{
	scanf("%d%d",&n,&k),j=k;
	for(int i=1;i<=n;i++)
		scanf("%d",a+i),f[a[i]]=i;
	ret=2e9;
	for(int i=1;i<=k+1;i++)
		ret=min(ret,a[i]);
//	printf("%d ",ret);
	if(!k)
	{
		for(int i=1;i<=n;i++)
			printf("%d ",a[i]);
		putchar('\n');
		return 0;
	}
	j=k;
	for(int i=1;i<=k+1;i++)
	{
		if(a[i]==ret)
		{ 
			for(int k=i;k<=n;k++)
			{
				while(j&&p&&st[p]>a[k])
					--p,--j;
				st[++p]=a[k];	
			}
			break;
		}
		--j;
	}
	while(j&&p)
		--p,--j;
	ret=2e9;
	for(int i=1;i<=k;i++)
		ret=min(ret,a[n-i+1]);
	j=k;
	for(int i=1;i<=k;i++)
	{
		q[--l]=a[n-i+1],--j;
		if(a[n-i+1]==ret)
		{
			g=i;
			for(int k=1;k<=n-i;k++)
				q[++r]=a[k];
			break;
		}
	}
	for(int i=l;i<=r;i++)
	{
		while((j||f[t[tp]]>=(n-g+1))&&tp&&t[tp]>q[i])
			j-=f[t[tp]]<(n-g+1),--tp;
		t[++tp]=q[i];
	}
	while((j||f[t[tp]]>=(n-g+1))&&tp)
		--tp,--j;
	for(int i=1;i<=max(tp,p);i++)
	{
		if(t[i]>st[i]||i>p)
		{
			for(int j=1;j<=p;j++)
				printf("%d ",st[j]);
			return 0;
		}
		if(t[i]<st[i]||i>tp)
		{
			for(int j=1;j<=tp;j++)
				printf("%d ",t[j]);
			return 0;
		}
	}
	for(int i=1;i<=tp;i++)
		printf("%d ",t[i]);
	return 0;
}
posted @ 2022-09-08 21:57  灰鲭鲨  阅读(20)  评论(0编辑  收藏  举报