codeforces891B Gluttony题解

来源:互联网 发布:车座套什么材质好 知乎 编辑:程序博客网 时间:2024/05/22 12:24

第一次做构造题..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的一种变换。
因此该做法是正确的。

原创粉丝点击