zoukankan      html  css  js  c++  java
  • AGC029C

    看来细节比较多...

    显然需要二分.
    考虑用贪心来判断当前的 (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 <bits/stdc++.h>
    #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;
    }
    
  • 相关阅读:
    可视化工具 kibana 的安装和使用
    常见的数据类型
    Elastic Search 分词器的介绍和使用
    基于 TCP 协议的网络编程
    Java7 的 NIO.2
    NIO(New IO)
    Java9 改进的对象序列化
    反射和泛型
    使用反射生成 JDK 动态代理
    使用反射生成并操作对象
  • 原文地址:https://www.cnblogs.com/hnfms-jerry/p/solution_agc029c.html
Copyright © 2011-2022 走看看