2 条题解

  • 0
    @ 2025-10-13 20:48:46

    我们来逐步说明:为什么一个元素 ai​ 能成为最终整个数组的值,当且仅当它是某个前缀的最小值,或是某个后缀的最大值。


    情况一:数组长度为 2

    如果数组只有两个元素,比如 [x,y],那么:

    • 使用一次前缀操作(选择整个数组),可以将数组变为 [min(x,y),min(x,y)]
    • 使用一次后缀操作(选择整个数组),可以将数组变为 [max(x,y),max(x,y)]

    因此,在两元素的情况下,最终数组只能变为两个数中的较小值或较大值,无法变为一个既非最小也非最大的值。


    情况二:ai​ 是前缀最小值或后缀最大值

    • 如果 aia_i​ 是从位置 1 到 i 的最小值,我们可以先对前 i 个元素执行前缀操作,使前 i 个数都变为 aia_i​。
      • 此时 aia_i​ 出现在数组开头。
      • 接下来可以通过一系列后缀操作,逐步将后面的元素也变为 aia_i​,最终使整个数组相同。
    • 类似地,如果 aia_i​ 是从位置 i 到末尾的最大值,我们可以先对从 i 开始的后缀执行后缀操作,使该后缀都变为 aia_i​。
      • 然后通过前缀操作逐步向前扩展,最终也能使整个数组变为 aia_i​。

    因此,只要 aia_i​ 是某个前缀的最小值或某个后缀的最大值,就存在一种操作序列,使整个数组最终都变为 aia_i​。


    情况三:aia_i​ 既不是前缀最小值,也不是后缀最大值

    假设 aia_i​ 不满足上述任一条件。

    我们记:

    • apa_p​ 为前缀 a1a_1​ 到 aia_i​ 中的最小值。由于 aia_i​ 不是前缀最小值,必有 apa_p​<aia_i​。
    • asa_s​ 为后缀 aia_i​ 到 ana_n​ 中的最大值。由于 aia_i​ 不是后缀最大值,必有 asa_s​>aia_i​。

    因此有:apa_p​<aia_i​<asa_s​,且 p<i<s。

    现在考虑任何一种操作序列。为了最终使整个数组变为 aia_i​,我们必须在某个时刻将 apa_p​ 和 asa_s​ 都变为 aia_i​,或者先改变其他位置,使得 aia_i​ 能逐步传播出去。

    但问题在于:

    • 如果我们尝试通过前缀操作改变包含 apa_p​ 的区间,由于 apa_p​ 是前缀最小值,该操作会将区间内所有元素变为 apa_p​ 或更小的值,而 aia_i​>apa_p​,因此 ai​ 也会被更新为更小的值,无法保留。
    • 如果我们尝试通过后缀操作改变包含 asa_s​ 的区间,由于 asa_s​ 是后缀最大值,该操作会将区间内所有元素变为 asa_s​ 或更大的值,而 aia_i​<asa_s​,因此 aia_i​ 也会被更新为更大的值。
    • 如果我们尝试通过后缀操作包含 apa_p​,那么该后缀必然包含 aia_i​,但由于 asa_s​>aia_i​,aia_i​ 不是该后缀的最大值,因此 aia_i​ 会被更新为更大的值。
    • 类似地,如果通过前缀操作包含 asa_s​,那么 aia_i​ 也会被包含,但由于 apa_p​<aia_i​,aia_i​ 不是最小值,也会被更新为更小的值。

    换句话说,任何能够影响 apa_p​ 或 asa_s​ 的操作,只要覆盖到 aia_i​,就会因为 aia_i​ 既不是最小也不是最大,而被更新为其他值

    因此,在所有可能的操作序列中,aia_i​ 很难保持不变,也无法逐步扩展到整个数组。


    最终结论

    综上所述,只有当 aia_i​ 是某个前缀的最小值或某个后缀的最大值时,才有可能通过一系列操作使整个数组变为 aia_i​。

    对于每个位置 i,我们只需检查:

    • aia_i​ 是否等于 a1a_1​ 到 aia_i​ 的最小值,或
    • aia_i​ 是否等于 aia_i​ 到 ana_n​ 的最大值。

    满足其一,则输出 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;
    }
    

    [2025 实验室一面] 雨露霜雪,雪霜露雨

    信息

    ID
    1103
    时间
    1000ms
    内存
    256MiB
    难度
    7
    标签
    递交数
    30
    已通过
    8
    上传者