2 条题解
-
0
我们来逐步说明:为什么一个元素 ai 能成为最终整个数组的值,当且仅当它是某个前缀的最小值,或是某个后缀的最大值。
情况一:数组长度为 2
如果数组只有两个元素,比如 [x,y],那么:
- 使用一次前缀操作(选择整个数组),可以将数组变为 [min(x,y),min(x,y)]
- 使用一次后缀操作(选择整个数组),可以将数组变为 [max(x,y),max(x,y)]
因此,在两元素的情况下,最终数组只能变为两个数中的较小值或较大值,无法变为一个既非最小也非最大的值。
情况二:ai 是前缀最小值或后缀最大值
- 如果 是从位置 1 到 i 的最小值,我们可以先对前 i 个元素执行前缀操作,使前 i 个数都变为 。
- 此时 出现在数组开头。
- 接下来可以通过一系列后缀操作,逐步将后面的元素也变为 ,最终使整个数组相同。
- 类似地,如果 是从位置 i 到末尾的最大值,我们可以先对从 i 开始的后缀执行后缀操作,使该后缀都变为 。
- 然后通过前缀操作逐步向前扩展,最终也能使整个数组变为 。
因此,只要 是某个前缀的最小值或某个后缀的最大值,就存在一种操作序列,使整个数组最终都变为 。
情况三: 既不是前缀最小值,也不是后缀最大值
假设 不满足上述任一条件。
我们记:
- 为前缀 到 中的最小值。由于 不是前缀最小值,必有 <。
- 为后缀 到 中的最大值。由于 不是后缀最大值,必有 >。
因此有:<<,且 p<i<s。
现在考虑任何一种操作序列。为了最终使整个数组变为 ,我们必须在某个时刻将 和 都变为 ,或者先改变其他位置,使得 能逐步传播出去。
但问题在于:
- 如果我们尝试通过前缀操作改变包含 的区间,由于 是前缀最小值,该操作会将区间内所有元素变为 或更小的值,而 >,因此 ai 也会被更新为更小的值,无法保留。
- 如果我们尝试通过后缀操作改变包含 的区间,由于 是后缀最大值,该操作会将区间内所有元素变为 或更大的值,而 <,因此 也会被更新为更大的值。
- 如果我们尝试通过后缀操作包含 ,那么该后缀必然包含 ,但由于 >, 不是该后缀的最大值,因此 会被更新为更大的值。
- 类似地,如果通过前缀操作包含 ,那么 也会被包含,但由于 <, 不是最小值,也会被更新为更小的值。
换句话说,任何能够影响 或 的操作,只要覆盖到 ,就会因为 既不是最小也不是最大,而被更新为其他值。
因此,在所有可能的操作序列中, 很难保持不变,也无法逐步扩展到整个数组。
最终结论
综上所述,只有当 是某个前缀的最小值或某个后缀的最大值时,才有可能通过一系列操作使整个数组变为 。
对于每个位置 i,我们只需检查:
- 是否等于 到 的最小值,或
- 是否等于 到 的最大值。
满足其一,则输出
1
,否则输出0
。#include <stdio.h> #define MAXN 200005 #define MIN(a, b) ((a) < (b) ? (a) : (b))//相当于最小值函数 #define MAX(a, b) ((a) > (b) ? (a) : (b))//相当于最大值函数 //利用三目运算符实现快速判断 int pre[MAXN], suf[MAXN], a[MAXN]; int main() { int t; scanf("%d", &t); while (t--) { int n; scanf("%d", &n); pre[0] = 1000000000; suf[n + 1] = -1; for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); pre[i] = MIN(pre[i - 1], a[i]); } for (int i = n; i >= 1; i--) { suf[i] = MAX(suf[i + 1], a[i]); } for (int i = 1; i <= n; i++) { if (a[i] == pre[i] || a[i] == suf[i]) { printf("1"); } else { printf("0"); } } printf("\n"); } return 0; }
信息
- ID
- 1103
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 30
- 已通过
- 8
- 上传者