CF1728B Best Permutation

考虑对权值产生贡献的数在哪里。

显然对于一个排列 pp,我们设 ii 为最大的下标位置,且进行到 iix=0x = 0。那么对答案有影响的是 pi+1p_{i+1}pnp_n

第一个结论,pi+1p_{i+1}pnp_n 严格单调递增。若存在 pjpj1(i<jn)p_j \leq p_{j-1}(i < j \leq n),那么进行到 jj 时,xx 一定会重新赋值为 00

第二个结论,排列最终权值 x2pn1x \leq 2 \cdot p_n - 1,进行到 nn 时,如果 x<pnx < p_n,那么 xx+pnx \leftarrow x + p_n,不然 x0x \leftarrow 0。显然最终的 x+pn<pn+pn=2pnx+p_n < p_n + p_n = 2 \cdot p_n

至此很好想,只需要令 i=n2,pn1=n1,pn=ni=n-2, p_{n-1} = n-1, p_n = n 即可,答案是最大的。

然而我们还需要构造 11ii

n0(mod2)n \equiv 0 \pmod 2,令 p=[n2,n3,n4,,nI1,,2,1,n1,n]p = [n-2, n - 3,n-4, \cdots, n-I-1, \cdots, 2, 1, n-1,n]。这里的 II 表示下标,且 1In21 \leq I \leq n - 2。可以发现 n2n-2n3n-3n4n-4n5n-5\cdots,两两抵消。

n1(mod2)n \equiv 1 \pmod 2,考虑在 pp 的前面构造 1,2,31, 2, 3,这时剩下的就是偶数,按照上述情况做即可。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;

const int N = 105;

int n, a[N], t;

int main()
{
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d", &n);
		if (!(n & 1))
		{
			int cur = 1;
			while (cur < n - 1)
			{
				a[cur] = n - (cur + 1);
				cur++;
			}
			a[n - 1] = n - 1;
			a[n] = n;
			for (int i = 1; i <= n; i++) printf("%d ", a[i]);
			printf("\n");
		}
		else
		{
			if (n == 5) printf("1 2 3 4 5\n");
			else
			{
				a[1] = 1, a[2] = 2, a[3] = 3;
				int cur = 4;
				while (cur < n - 1)
				{
					a[cur] = n - (cur - 2);
					cur++;
				}
				a[n - 1] = n - 1;
				a[n] = n;
				for (int i = 1; i <= n; i++) printf("%d ", a[i]);
				printf("\n");
			}
		}
	}
	return 0;
}
posted @   HappyBobb  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示