P7852 「EZEC-9」Yet Another Easy Problem

题目传送门

思路

构造思维题

题意比较清楚,这里就不再阐述了。

我们可以进行分情况讨论,我们先假定在这里构造的排列是介于 1 1 1 n n n 之间的数。

情况1: m = 0 m=0 m=0

比较显然,他不能进行操作,我们就直接输出一个字典序最大的,即从 n n n 1 1 1 倒着输出即可。

情况2: m ≥ n − 1 m \ge n-1 mn1

可以至少操作 n − 1 n-1 n1 次,既然他可以操作 n − 1 n-1 n1 次,也就是说,他可以每个数字都移动一次。说白了,就是无论你给他什么序列,他只要可以操作 n − 1 n-1 n1 次,他都可以把这个序列变成 1 1 1 2 2 2 3 3 3 n n n。因此,在这种情况当中,无论你输出什么都是正确的。

情况3:非以上两种情况的一般情况

为了尽量浪费他的操作,我们可以把 n n n 直接放在前面,因为这样他就一定会把 n n n 1 1 1 进行交换,因为他希望字典序最小。 为了让他交换的成果最小,我们就把 1 1 1 放在第二个位置上,因为就算它就换了,他的 n n n 却仍然只往后跑了一位。 很显然,第二次操作,他就会让 n n n 2 2 2 进行交换。所以,为了让他成果更小,我们就把 2 2 2 放在第三位上。 以此类推,他要操作 m m m 次,我们就把前 m m m 个数放在这个数的后一位上,然后在第一位上放 n n n 。 这样的话,他无论怎么换,他的 n n n 也只能跑到第 m + 1 m+1 m+1 这个位置,而在 m + 2 m+2 m+2 后面的数,我们为了保证字典序最大,我们就从 n − 1 n-1 n1 输出到 m + 1 m+1 m+1,然后这样的话,我们就构造完成了,并且可以保证他的字典序在操作完之后是最大的。

代码

#include<bits/stdc++.h>
using namespace std;
int t,n,m;
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		if(m==0)//特判m=0
		{
			for(int i=n;i>=1;--i)
			cout<<i<<" ";
			cout<<endl;
		}
		else if(m>=n-1)//特判 m>=n-1
		{
		    for(int i=1;i<=n;++i)
		    cout<<i<<" ";
			cout<<endl;
		}
		else
		{
			cout<<n<<" ";//先输出n
			//根据思路里的策略进行输出
			for(int i=1;i<=m;++i)
			cout<<i<<" ";
			for(int i=n-1;i>m;--i)
			cout<<i<<" ";
			cout<<endl;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值