码迷,mamicode.com
首页 > 其他好文 > 详细

Educational Codeforces Round 97 (Rated for Div. 2)

时间:2020-10-29 10:45:29      阅读:39      评论:0      收藏:0      [点我收藏+]

标签:for   开始   ble   contest   upd   make   最长上升子序列   math   ORC   

E. Make It Increasing Educational Codeforces Round 97 (Rated for Div. 2)

题目连接

题解:

因为b[i]的值是确定,所以知道操作 b[i] 到b[i - 1]的区间, 当 \(a[i] - a[j] < i - j (i > j)\) 那么可以证明一定无法构成, 所以先判断是否可以构造,如果都满足, 那么对与每段 \(b[i - 1]\)\(b[i]\) 可以先将\(a[i] = a[i] - i\)

这样做的目的是保证存在 \(a[i] > a[j] ,且 i > j\) 那么就是且以 \(b[i - 1]\)开始 \(b[i]\) 结束的最长上升子序列, 可以用二分优化到 n * log(n)也可以用线段树优化。

代码:

    #include<bits/stdc++.h>
    using namespace std;
     
    const int N = 5e5 + 7;
    typedef long long ll;
     
    ll a[N], n, k, b[N];
    int rt;
     
    int tree[40 * N], ls[40 * N], rs[40 * N], dp[N];
    int top = 1;
    #define m (l + r) / 2
    void update(int v, int pos, int l, int r, int &node) {
        if (node == 0) node = top++;
        if (l == r) {
            tree[node] = v;
            return;
        }
        if (pos <= m) update(v, pos, l, m, ls[node]);
        else update(v, pos, m + 1, r, rs[node]);
        tree[node] = max(tree[ls[node]], tree[rs[node]]);
    }
     
    int query(int ql, int qr, int l, int r, int node) {
        if (ql <= l && qr >= r) {
            return tree[node];
        }
        int ans = 0;
        if (ql <= m) ans = max(ans, query(ql, qr, l, m, ls[node]));
        if (qr > m) ans = max(ans, query(ql, qr, m + 1, r, rs[node]));
        return ans;
    }
     
    int work(int l, int r) {
        int maxn = n + 2;
        for (int i = l; i <= r; i++) {
            dp[i] = 0;
        }
        for (int i = l + 1; i <= r; i++) {
            if (a[i] >= a[l]) {
                dp[i] = 2;
            } else {
                dp[i] = -1e8;
            }
        }
     
        for (int i = l + 1; i <= r; i++) {
            dp[i] = max(dp[i], query(1, a[i], 1, maxn, rt) + 1);
            if (dp[i] > 1)
            update(dp[i], a[i], 1, maxn, rt);
        }
     
        for (int i = l; i <= r; i++) {
            update(0, a[i], 1, maxn, rt);
        }
        
        if (dp[r] < 2) {
            return -1;
        }
        return (r - l + 1) - dp[r];
        
    }
     
    vector<int> g;
     
    int get_id(int x) {
        return lower_bound(g.begin(), g.end(), x) - g.begin() + 1;
    }
     
    int main() {
        ios::sync_with_stdio(0);
        cin >> n >> k;
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
            a[i] = a[i] - i;
            g.push_back(a[i]);
        }
        sort(g.begin(), g.end());
        g.erase(unique(g.begin(), g.end()), g.end());
        for (int i = 1; i <= k; i++) {
            cin >> b[i];
        }
     
        for (int i = 1; i <= n; i++) {
            a[i] = get_id(a[i]);
        }
        b[0] = 0;
        b[k + 1] = n + 1;
        a[0] = 0;
        a[n + 1] = n + 2;
     
        int ans = 0;
     
        for (int i = 1; i <= k + 1; i++) {
            int cnt = work(b[i - 1], b[i]);
            if (cnt < 0) {
                cout << -1 << endl;
                return 0;
            }
            ans += cnt;
        }
        cout << ans << endl;
     
     
    }

Educational Codeforces Round 97 (Rated for Div. 2)

标签:for   开始   ble   contest   upd   make   最长上升子序列   math   ORC   

原文地址:https://www.cnblogs.com/BOZHAO/p/13894442.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!