[CF1793B] Fedya and Array 题解

· · 题解

题目链接

洛谷

Codeforces

题意分析

有一个长度为 n 的数组 a,排列成一个圆,相邻两个数的差为 1

注意,元素 a_n 和 元素 a_1 是相邻元素。

我们把同时小于左右两个相邻元素的元素值称为局部最大值,把同时小于左右两个相邻元素的元素值称为局部最小值。

由于 相邻两个数的差为 1,所以局部最大值相邻的数一定都比它小 1,而局部最小值相邻的数一定都比它大 1

现在,题目告诉我们 所有局部最大值的和 —— x 与 所有局部最小值的和 —— y,要我们求出 任何最小长度的匹配数组。

题目解法

这道题其实不需要很复杂的算法,

只要找到规律,就变得很简单了。

我们可以举个例子:

x = 5~~~y=-2

可以看到,这个例子中:

唯一的局部最大值就是正上方 4 5 4 中的 5,而所有局部最大值的和自然也就是 5 了。

唯一的局部最小值就是正下方 -1 -2 -1 中的 -2,而所有局部最小值的和自然也就是 -2 了。

满足条件,所以我们可以推导出:

也就是输出 x,x-1,x-2,...,y,y+1,y+2,...,x-1

但是题目还问了一共有多少个数,通过上图可以发现,

至少需要 $2(x-y)$ 个数。 ##### 可行性证明 $x \to y \to (x-1)$ 可以确保 $x$ 相邻的数都比它小 $1$,而 $y$ 相邻的数都比它大 $1$。 由于 $x \to y$ 和 $y \to (x-1)$ 都是有序地 $+1$ 或 $-1$ 的,所以可以确保只有唯一一个局部最大值和局部最小值,从而确保所有局部最大值和所有局部最小值为 $x$ 和 $y$。 时间复杂度为 $\mathcal{O}(∑n)$。 ### [AC](https://www.luogu.com.cn/record/102111258) code ```cpp #include<bits/stdc++.h> using namespace std; int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while (t--){ int x,y; cin >> x >> y; cout << 2*(x-y) << endl; for (int i=x;i>=y;i--){ cout << i << " "; } for (int i=y+1;i<x;i++){ cout << i << " "; } cout << endl; } return 0; } ```