育华周赛 第二十七期

已结束 乐多 开始于: 2026-5-23 8:30 54 小时 主持人: 17

育华周赛 第二十七期

T5

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll n, q;
ll a[1000010];
ll b[1000010];
ll c[1000010];

ll pre[1000010]; // c[i] == 1, pre[i]连接的最左边的1的位置
ll nxt[1000010]; // c[i] == 1, nxt[i]连接的最右边的1的位置

ll lz[1000010]; // lz[i]表示i左边的0 的最大位置包括i
ll rz[1000010]; // rz[i]表示i右边的0 的最小位置包括i

ll g[1000010]; // g[i]表示以c[i]改为1增加的贡献
ll s[1000010]; // s[i]表示以g[i]的贡献次数  (可以完整贡献的次数)
ll gg[1000010]; // gg[i]第i个位置被修改的贡献 (会被左右切割的情况)
ll sum[1000010];;
ll ansi, ansv;
ll ans[1000010];

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

    cin >> n >> q;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    for (int i = 1; i <= n; i++) {
        cin >> b[i];
        c[i] = a[i] >= b[i];
    }

    for (int i = 1; i <= n; i++) {
        pre[i] = c[i] == 0 ? 0 : pre[i - 1] ? pre[i - 1] : i;
        lz[i] = c[i] ? lz[i - 1] : i;
        sum[i] = c[i] ? sum[i - 1] + i - pre[i] + 1 : sum[i - 1];
    }
  rz[n + 1] = n+1;
    for (int i = n; i >= 1; i--) {
        nxt[i] = c[i] == 0 ? 0 : nxt[i + 1] ? nxt[i + 1] : i;
        rz[i] = c[i] ? rz[i + 1] : i;
    }

    for (int i = 1; i <= n; i++) {
        if (!c[i]) {
            ll left = pre[i-1]? i-pre[i - 1] + 1:1;
            ll right = nxt[i + 1]? nxt[i + 1] - i + 1:1;
            g[i] = left * right;
        }
    }

    for (int i = 1; i <= q; i++) {
        ll l, r;
        cin >> l >> r;

        ll pll = rz[l];    // 区间里最左边的0
        ll prr = lz[r];    // 区间里最后边的0

        // 说明区间没有0
        if (pll > prr) {
            // 直接计算区间的贡献
            ansv += (r - l + 1) * (r - l + 2) / 2;
            continue;
        }
        // 右半部分通过前缀和求得
        ansv += sum[r] - sum[pll];
        // 看看左边有多少个1  计算贡献度
        ansv += (pll - l) * (pll - l + 1) / 2;

        // 1111011111   这种形态 那么这个0 变成1 的贡献度 记录下来
        if (pll == prr) {
            gg[pll] += (pll - l + 1) * (r - pll + 1);
        }
        else {
            // 11110.........0111111   这种形态   把这两个0变1 的贡献度记录下来
            gg[pll] += (pll - l + 1) * (c[pll + 1] ? (nxt[pll + 1] - pll + 1) : 1);
            gg[prr] += (r - prr + 1) * (c[prr - 1] ? (prr - pre[prr - 1] + 1) : 1);

            // 两个0之间的0 的贡献  只记录次数  因为他们的贡献度是g[i]
            // 这是差分  用前缀和求某个位置的值
            s[pll + 1]++;
            s[prr]--;
        }
    }
    for (int i = 1; i <= n; i++) {
        s[i] += s[i - 1];
        if (!c[i]) {
            // 修改i这个位置的贡献度
            ans[i] = g[i] * s[i] + gg[i];
            if (ans[i] > ans[ansi]) {
                ansi = i;
            }
        }
    }
    cout << ansi << " " << ans[ansi] + ansv << "\n";
    return 0;
}


状态
已结束
规则
乐多
题目
6
开始于
2026-5-23 8:30
结束于
2026-5-25 14:30
持续时间
54 小时
主持人
参赛人数
17