1 条题解

  • 0
    @ 2026-5-5 13:49:43

    CF1990B Array Craft 题解

    题意回顾

    给定三个整数 n,x,yn, x, y1y<xn1 \le y < x \le n),构造一个长度为 nn、仅由 111-1 组成的数组 aa,使得:

    • 最大前缀位置等于 xx:即 xx 是满足 $\sum_{j=1}^i a_j = \max\limits_{k=1}^n \sum_{j=1}^k a_j$ 的最小下标 ii
    • 最大后缀位置等于 yy:即 yy 是满足 $\sum_{j=i}^n a_j = \max\limits_{k=1}^n \sum_{j=k}^n a_j$ 的最大下标 ii

    构造方法

    将数组分为三段:

    1. 左段 [1,y1][1, y-1]:从右往左(下标递减)交替填入 1,1,1,1,-1, 1, -1, 1, \dots,即下标与 y1y-1 同奇偶的位置填 11,否则填 1-1
    2. 中段 [y,x][y, x]:全部填 11
    3. 右段 [x+1,n][x+1, n]:从左往右交替填入 1,1,1,1,-1, 1, -1, 1, \dots,即从 x+1x+1 开始奇数位填 1-1,偶数位填 11

    代码中的实现:

    for (int i = y - 1; i; --i)          // 左段,从右往左
        cout << (i & 1 ? "-1 " : "1 ");
    for (int i = y; i <= x; ++i)         // 中段
        cout << "1 ";
    for (int i = 1, tmp = n - x; i <= tmp; ++i) // 右段
        cout << (i & 1 ? "-1 " : "1 ");
    

    正确性证明

    1. 最大前缀位置 =x= x

    观察前缀和的变化:

    • 左段 [1,y1][1, y-1]:交替填 1,1-1, 1,使得前缀和在 1100 之间反复震荡(具体取决于 y1y-1 的奇偶性),但始终保持 1\le 1。到位置 y1y-1 时前缀和 1\le 1
    • 进入中段 [y,x][y, x](全 11)后,前缀和从位置 y1y-1 的值开始,每个位置 +1+1,单调递增。
    • 位置 xx 处前缀和达到全局最大值。因为之后进入右段 [x+1,n][x+1, n],交替填入 1,1-1, 1,使得前缀和每隔一步减少 11 或不变,不会再超过 xx 处的值。

    此外,若存在某个 i<xi < x 使得前缀和也等于最大值,必须保证 xx最小的这样的下标。由于中段全 11,前缀和在 [y,x][y, x] 严格单调递增,故 xx 之前的任何位置前缀和都严格小于 xx 处。左段的前缀和始终小于等于 11,不可能达到 xx 处的值(中段至少有一个 11,所以 xx 处前缀和 \ge 前面最大值 +1+1)。因此 xx 确实是唯一且最小的最大值位置。

    2. 最大后缀位置 =y= y

    观察后缀和的变化:

    • 右段 [x+1,n][x+1, n]:交替填 1,1-1, 1,后缀和(从右往左看)在 0011 之间震荡,始终 1\le 1
    • 中段 [y,x][y, x](全 11):从右往左看,后缀和在 [y,x][y, x] 区间内严格单调递增(因为每个位置都是 11)。
    • 左段 [1,y1][1, y-1]:交替填 1,1-1, 1,后缀和经历 1,1-1, 1 交替,始终 1\le 1

    整个后缀和的最大值出现在 yy 处。因为从 nn 往左扫,后缀和先是 1\le 1,经过中段 [y,x][y, x] 时逐渐增大,在 yy 处达到最大;再往左,后缀和因交替填 1,1-1,1 而下降,不会再超过 yy 处的值。同时 yy最大的使得后缀和等于最大值的下标,因为中段 [y,x][y, x] 内后缀和严格递减(从左往右看是递增,从右往左是递减),所以 yy 之后的位置后缀和都严格小于 yy 处。


    复杂度

    每组数据只需 O(n)O(n) 时间输出。所有数据 nn 总和 105\le 10^5,完全可以通过。


    参考代码

    #include <bits/stdc++.h>
    #define I return
    #define AK 0
    #define IOI ;
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    int t, n, x, y;
    int main() {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
        cin >> t;
        while (t--) {
            cin >> n >> x >> y;
            for (int i = y - 1; i; --i)
                cout << (i & 1 ? "-1 " : "1 ");
            for (int i = y; i <= x; ++i)
                cout << "1 ";
            for (int i = 1, tmp = n - x; i <= tmp; ++i)
                cout << (i & 1 ? "-1 " : "1 ");
            cout << '\n';
        }
        I AK IOI
    }
    
    • 1

    信息

    ID
    6897
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者