第一次做构造题..orz…
.一开始以为是状压DP啥的想了半天发现一脸不可做
于是生无可恋的洗洗睡了
早晨看到题解和AC代码感觉只有一个:蛤?
惯例说说题意。
一个由
n
个元素构成的数列
如果满足
现在给你这样的
T
,输出可能的一个
做法很玄妙。
首先,我们对
T
进行排序,构成
然后,用题解的话说,”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
大交换到第
因此任何数列都可以等效这样一个数列:
a:ai=i
,对这一数列的操作相当于整个向左拖动并把最小的那个扔到最后去,形成数列
b
。
考虑第一个元素,
如果
否则,令
M′=∁Ma
,那么
∑bi<∑ai(i∈M′)
,总和不变,所以
∑bi>∑ai(i∈M)
恒成立。
综上所述,
b
是符合条件的
因此该做法是正确的。