Logo FiraCode 的博客

博客

题解:CF1692H Gambling

...
FiraCode
2025-12-01 12:55:24
什么意思呢

本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2024-08-15 17:27:02

显然的,对于一个 $a_i$,我们把等于 $a_i$ 的设为 $1$,其他设为 $-1$,那么就转化成了求最大字段和。

考虑顺着枚举 $a_i$,对于当前 $i$ 暴力往后扫求以 $i$ 开始的极长区间 $[i,j]$,使得对于所有区间 $[i,k]$ 其中 $(i \le k \le j)$ 满足这个区间的和 $\ge 0$。

那么对于这个区间 $[i,j]$ 中所有的 $=a_i$ 的 $k$ 打上标记,下一次若遇到标记就不用再扫一遍了。

时间复杂度约为 $O(n \sqrt n)$,因为对于个数 $\le \sqrt n$ 的数字,每个的贡献是 $O(\sqrt n)$。而对于个数 $> \sqrt n$ 的数字,最多也就 $O(\sqrt n)$,所以这部分也就 $O(n \sqrt n)$,所以总时间复杂度为 $O(n \sqrt n)$。

#include <bits\/stdc++.h>

using namespace std;

int T;
int n;
int a[200010];

int main() {
    scanf("%d", &T);
    for (int Tc = 1; Tc <= T; ++Tc) {
        unordered_map<int, int> st;

        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);

        int ans = 0, v, l, r;
        for (int i = 1; i <= n; ++i) {
            if (st.count(i)) continue;

            int s = 0;
            for (int j = i; j <= n; ++j) {
                if (a[j] == a[i]) ++s, st[j] = 1;
                else --s;

                if (s > ans) {
                    ans = s;
                    v = a[i];
                    l = i, r = j;
                }
                if (s < 0) break;
            }
        }

        printf("%d %d %d\n", v, l, r);
    }
    return 0;
}

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。