CF1108E2 Array and Segments (Hard version)(待更新)

题目地址:CF1108E2

弱化版题解

加强版跟弱化版唯一的区别就是 \(n\) 的范围增大了,但是 \(m\) 没有变

这启发我们离散化

将离散化后的每一个区间看作一个点,再用弱化版的算法即可

时间复杂度为 \(O(m^2+nm)\)

代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 100006, M = 306;
int n, m, a[N], l[M], r[M];
int b[M<<1], tot, mx[M<<1], mn[M<<1], c[M<<1];
vector<int> ans[M<<1];

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for (int i = 1; i <= m; i++) {
        scanf("%d %d", &l[i], &r[i]);
        b[++tot] = l[i];
        b[++tot] = ++r[i];
    }
    b[++tot] = 1;
    b[++tot] = n + 1;
    sort(b + 1, b + tot + 1);
    tot = unique(b + 1, b + tot + 1) - (b + 1);
    for (int i = 1; i <= m; i++) {
        l[i] = lower_bound(b + 1, b + tot + 1, l[i]) - b;
        r[i] = lower_bound(b + 1, b + tot + 1, r[i]) - b;
    }
    for (int i = 1; i < tot; i++) {
        mx[i] = mn[i] = a[b[i]];
        for (int j = b[i] + 1; j < b[i+1]; j++) {
            mx[i] = max(mx[i], a[j]);
            mn[i] = min(mn[i], a[j]);
        }
    }
    int num = 0, now;
    for (int x = 1; x < tot; x++) {
        memset(c, 0, sizeof(c));
        for (int i = 1; i <= m; i++) {
            if (l[i] <= x && r[i] > x) continue;
            --c[l[i]];
            ++c[r[i]];
            ans[x].push_back(i);
        }
        int s = 0, t = 0, k;
        for (int i = 1; i < tot; i++) {
            s += c[i];
            if (!t || mn[i] + s < k) k = mn[t=i] + s;
        }
        if (!num || mx[x] - k > now) now = mx[num=x] - k;
    }
    cout << now << endl << ans[num].size() << endl;
    for (unsigned int i = 0; i < ans[num].size(); i++)
        printf("%d ", ans[num][i]);
    puts("");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xht37/p/10322344.html
今日推荐