codeforces891B Gluttony题解

本文介绍了一种构造题的解决方法,通过排序和位置移动得到目标数列T′。文章详细解释了做法,并通过数学证明了这种方法的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一次做构造题..orz…
.一开始以为是状压DP啥的想了半天发现一脸不可做
于是生无可恋的洗洗睡了
早晨看到题解和AC代码感觉只有一个:蛤?


惯例说说题意。
一个由n个元素构成的数列T(满足互异性),假定TT的一个排列。
如果满足MS,其中S表示1n构成的集合,有TMiTMi恒成立,则T为所求的一个集合。
现在给你这样的T,输出可能的一个T。如果不存在输出1


做法很玄妙。
首先,我们对T进行排序,构成T1
然后,用题解的话说,”shift it by one”,也就是整个移动一下。
怎么移动呢?按照排序后的位置+1重新排一下,有点类似莫队的离散化过程。
玄学题,先放代码吧。证明之后再说。

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n;
struct node{
    int x, pos;
}m[25];
int ansT[25];
bool cmp(node a, node b) {
    return a.x < b.x;
}
int main() {
    cin>>n;
    for(int i = 1; i <= n; ++i) cin>>m[i].x, m[i].pos = i;
    sort(m + 1, m + n + 1, cmp);
    ansT[m[1].pos] = m[n].x;
    for(int i = 2; i <= n; ++i) ansT[m[i].pos] = m[i - 1].x;
    for(int i = 1; i <= n; ++i) cout<<ansT[i]<<" ";
    return 0;
} 

接下来就是这种做法正确性证明了。
一开始我也百思不得其解,然后看了讨论,顿悟:
这个步骤相当于将第k大交换到第k1大的位置上。
因此任何数列都可以等效这样一个数列:a:ai=i,对这一数列的操作相当于整个向左拖动并把最小的那个扔到最后去,形成数列b
考虑第一个元素,
如果a1M,那么bi<ai(iM)是恒成立的,因为都变小了。
否则,令M=Ma,那么bi<ai(iM),总和不变,所以bi>ai(iM)恒成立。
综上所述,b是符合条件的a的一种变换。
因此该做法是正确的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值