mayoko’s diary

プロコンとかいろいろ。

Codeforces Round #333 (Div. 2) B. Approximating a Constant Range

Codeforces Round #333 (Div. 2) に参加しました。D 解きたかった〜〜〜〜〜〜〜〜〜〜

解法

しゃくとり法的にやります。

しゃくとり法のやり方はいろいろあったと思いますが, 僕はセグメント木でやりました。seg1[l, r] = (区間[l, r] の最大値), seg2[l, r] = (区間[l, r] の最小値)として, seg1[l, r] - seg[l, r] <= 1 となるようにしゃくとりしていきます。

ただ一番賢いのは multiset を使うことだったと思います…

const int MAXN = 100100;
int a[MAXN];

class segTree1 {
public:
    int N;
    vector<int> seg;
    segTree1(int V) {
        N = 1;
        while (N < V) N *= 2;
        seg.resize(2*N-1, MAXN);
    }
    void update(int k, int x) {
        k += N-1;
        seg[k] = x;
        while (k) {
            k = (k-1) / 2;
            seg[k] = min(seg[2*k+1], seg[2*k+2]);
        }
    }
    int get(int a, int b, int k, int l, int r) {
        if (r <= a || b <= l) return MAXN;
        if (a <= l && r <= b) return seg[k];
        return min(get(a, b, 2*k+1, l, (l+r)/2), get(a, b, 2*k+2, (l+r)/2, r));
    }
    int get(int a, int b) {
        return get(a, b, 0, 0, N);
    }
};

class segTree2 {
public:
    int N;
    vector<int> seg;
    segTree2(int V) {
        N = 1;
        while (N < V) N *= 2;
        seg.resize(2*N-1, -1);
    }
    void update(int k, int x) {
        k += N-1;
        seg[k] = x;
        while (k) {
            k = (k-1) / 2;
            seg[k] = max(seg[2*k+1], seg[2*k+2]);
        }
    }
    int get(int a, int b, int k, int l, int r) {
        if (r <= a || b <= l) return -1;
        if (a <= l && r <= b) return seg[k];
        return max(get(a, b, 2*k+1, l, (l+r)/2), get(a, b, 2*k+2, (l+r)/2, r));
    }
    int get(int a, int b) {
        return get(a, b, 0, 0, N);
    }
};


int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    segTree1 seg1(n);
    segTree2 seg2(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        seg1.update(i, a[i]);
        seg2.update(i, a[i]);
    }
    int ans = 1;
    int s = 0, t = 1;
    for (;;) {
        while (t <= n) {
            if (seg2.get(s, t) - seg1.get(s, t) <= 1) {
                t++;
            } else break;
        }
        ans = max(ans, t-s-1);
        if (t > n) break;
        while (seg2.get(s, t) - seg1.get(s, t) > 1) s++;
        ans = max(ans, t-s);
    }
    cout << ans << endl;
    return 0;
}