【构造】0605 Another Array Problem

题意:
给定一个长度为 n n n 的数组 a a a,每次可以选择两个下标 i , j i,j i,j,满足 1 ≤ i < j ≤ n 1\leq i1i<jn,然后将下标 k ∈ [ i , j ] k \in[i,j] k[i,j] 的元素都修改为 ∣ a i − a j ∣ |a_i-a_j| aiaj ,可以进行若干次操作,问可以使得 a a a 的所有元素之和最大是多少。

数据范围: 1 ≤ n ≤ 1 0 5 , 1 ≤ a i ≤ 1 0 9 1\leq n\leq 10^5,1\leq a_i\leq 10^9 1n105,1ai109

题解:

  • 考虑 n = 2 n=2 n=2 的情况,此时要么选择一次 1 , 2 1,2 1,2,然后数组变为 [ ∣ a 1 − a 2 ∣ , ∣ a 1 − a 2 ∣ ] [|a_1-a_2|,|a_1-a_2|] [a1a2,a1a2],要么就不选择。答案为: m a x ( a 1 + a 2 , 2 × ∣ a 1 − a 2 ∣ ) max(a_1+a_2,2\times |a_1-a_2|) max(a1+a2,2×a1a2)

  • 考虑 n ≥ 4 n\geq 4 n4的情况,数组最大元素 m a x v maxv maxv a i = m a x v a_i=maxv ai=maxv,那么 [ 1 , i − 1 ] [1,i-1] [1,i1] 或者 [ i + 1 , n ] [i+1,n] [i+1,n] ,必然有一个区间的大于等于 2 2 2。对其中一个区间操作两次,使得这个区间为 0 0 0,然后再操作 [ 1 , n ] [1,n] [1,n],使得 a a a 都变成了 m a x v maxv maxv

  • 考虑 n = 3 n=3 n=3 的情况

    • 数组最大元素 m a x v maxv maxv a 1 a_1 a1 或者 a 3 a_3 a3,可以用上述的方式使得整个数组都变成 m a x v maxv maxv

    • 数组最大元素 m a x v maxv maxv a 2 a_2 a2

      • 不进行任何操作: a 1 + a 2 + a 3 a_1+a_2+a_3 a1+a2+a3
      • 将区间的值操作为同一个值,这个值必然需要最大,有几种可能值
        • a 2 − min ⁡ ( a 1 , a 3 ) a_2-\min(a_1,a_3) a2min(a1,a3)
        • a 1 a_1 a1
        • a 2 a_2 a2
        • ∣ a 2 − a 1 ∣ |a_2-a_1| a2a1
        • ∣ a 2 − a 3 ∣ |a_2-a_3| a2a3

      为什么要么不操作,要么就把所有值都操作为相同呢?
      因为我们操作到相同的值必然是一个最大值,如果最左边和最右边的值不同,那么必然存在一个最大值,我们必然可以在一些操作后,使得所有值都成为初始两边的较大值。

代码:

    #include 
    using namespace std;

    void solve() {
        int n;
        cin >> n;

        vector<int> a(n);
        for (int i = 0; i < n; ++i) cin >> a[i];

        if (n == 2) {
            cout << max(a[0] + a[1], 2 * abs(a[0] - a[1])) << "\n";
            return;
        }

        int minv = 0x3f3f3f3f;
        int maxv = 0;
        for (int i = 0; i < n; ++i) {
            maxv = max(maxv, a[i]);
            minv = min(minv, a[i]);
        }

        if (n >= 4 || a.front() == maxv || a.back() == maxv) {
            cout << 1ll * n * maxv << "\n";
            return;
        }

        // 此时 maxv 居中

        // 不变
        long long ans = accumulate(a.begin(), a.end(), 0ll);
		// 操作为最大值
        ans = max({ans,  3ll * (maxv - minv), 3ll * a[0], 3ll * a[2], 3ll * (maxv - a[0]), 3ll * (maxv - a[2])});

        cout << ans << "\n";
    }

    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);

        int T = 1;
        cin >> T;
        while (T--) solve();

        return 0;
    }

你可能感兴趣的:(#,构造题,c++,算法,数据结构)