AGC029C - Lexicographic constraints 题解

当时考试的时候就遇到了这道题...然而并没有写出来.
现在看来感觉细节的确比较多...

显然需要二分.
考虑用贪心来判断当前的 \(mid\) 是否可行, 从 \(1\) 枚举到 \(n\):

  • 如果 \(a_i > a_{i-1}\), 那么直接在后面添 \(0\) 即可.
  • 如果 \(a_i \leq a_{i-1}\), 那么贪心, 在 \(a_{i-1}\) 的基础上找到第一个 \(\leq a_i\) 且值不为 \(mid\) 的位置, 然后将它的值 \(+1\).

如果某次找不到这样的位置了则说明 \(mid\) 不行.
考虑到直接维护是 O(值域) 的, 可能接受不了, 但每次修改都是连续的一段.
所以这个东西可以用栈来维护...

贴上代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
#define N 200200
#define fi first
#define se second
#define pii pair<int, int>
using namespace std;

int n, a[N], top;
pii stk[N];

inline bool check(int mid) {
    stk[0] = make_pair(0, 0);
    stk[top = 1] = make_pair(1, a[1]);
    for (int i = 2; i <= n; ++i) {
        if (a[i] > a[i - 1]) {
            while (top && stk[top].fi == 1) 
                --top;
            stk[++top] = make_pair(1, a[i]);
        } else {
            int now = 0;
            while (top && stk[top].se >= a[i])
                now = stk[top--].fi;
            if (now < mid) {
                if (stk[top].se != a[i] - 1)
                    stk[++top] = make_pair(now, a[i] - 1);
                else while (top && stk[top].fi == now + 1) --top;
                stk[++top] = make_pair(now + 1, a[i]);
            } else {
                if (!top) return false;
                now = stk[top].fi;
                int pos = stk[top].se;
                if (stk[top - 1].se == pos - 1) {
                    if (top) for (--top; top && stk[top].fi == now + 1; --top);
                    stk[++top] = make_pair(now + 1, pos);
                } else stk[top].se--, stk[++top] = make_pair(now + 1, pos);
                stk[++top] = make_pair(1, a[i]);
            }
        }
    }
    return true;
}

int main() {

    cin >> n;
    bool chk = 1;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", a + i);
        if (a[i] <= a[i - 1]) chk = false;
    }
    if (chk) return puts("1"), 0;

    int l = 2, r = n - 1, res = n;
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (check(mid)) r = (res = mid) - 1;
        else l = mid + 1;
    }

    cout << res << endl;

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hnfms-jerry/p/solution_agc029c.html