E题 双指针

注:下标从 0 开始。

单考虑从左到右,枚举 i,意味前 个数我们使用操作 1 变为红色( 的取值范围是 ),后面用操作 2 来完成题意。

取值范围:因为取了 个以后,剩下一个,没必要使用操作 2。

此时可以再利用一个变量 r,双指针维护一段区间 表示一段没有重复元素的区间。

继续考虑操作 2 的使用范围,是

实现

用两个变量 记录使用操作 1 的代价和操作 2 的代价。

因为 表示的是取了几个数,所以在更新答案之后再将其更新为 ,而 只需要在利用双指针扩展 的时候利用 更新即可。

代码

#include <bits/stdc++.h>

using i64 = long long;

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

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

    i64 ans = 2e18;
    {
        std::map<int, int> Seen;
        auto del = [&](int x) {
            Seen[x] --;
        };
        auto add = [&](int x) {
            if (Seen[x]) return false;
            Seen[x] ++;
            return true;
        };

        i64 Pre = 0, Suf = 1e18;
        for (int i = 0, r = 0; r < n; i ++ ) {
            for (; r < n; r ++) {
                Suf = std::min(Suf, 1LL * a[r] * (n - r));
                if (!add(a[r])) break;
            }
            ans = std::min(ans, Pre + Suf);
            if (r == n) ans = std::min(ans, Pre);
            Pre = 1LL * a[i] * (i + 1);
            del(a[i]);
        }
    }

    std::cout << ans << "\n";
    return 0;
}