• 多校 1010 Taotao Picks Apples(补题)


    》》点击进入原题《《

     思路:题解很有意思,适合线段树进阶 

    考虑每次修改不叠加,因此我们可以从如何对原序列进行预处理着手。
    通过观察可以发现,将原序列从任意位置断开,我们可以通过分别维护左右段的某些信息来拼接
    得到答案。
    对于左段来说:

    • 需要知道最大值的位置,以及到达最大值需要几步;
    • 使用 ST 维护信息。
    对于右段来说:
    • 由于前半部分的信息未知,因此我们需要维护从每个位置开始到结尾可以走几步;
    • 从后往前做 DP,每次找出右边第一个比自己大的数,答案就是它的 DP 值 +1。
    对于每次询问:
    • 考虑这个数左边的部分加上这个数之后的答案和最大值;
    • 再找到右边第一个大于左半部分最大值的数,答案相加即可。
    预处理使用 ST 表,每次查询需要一个二分,总复杂度 O(nlogn+qlogn)。 —题解来自HDU

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    #define lson l,m,o<<1
    #define rson m+1,r,o<<1|1
    
    const int maxn = 1e5 + 10;
    int a[maxn], d1[maxn], d2[maxn];
    int tree[maxn << 2], vis[maxn << 2];
    int ans, cur;
    
    void build(int l, int r, int o){
        if (l == r){
            tree[o] = a[l];
            vis[o] = l;
            return;
        }
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        tree[o] = max(tree[o << 1], tree[o << 1 | 1]);
        if (tree[o << 1] >= tree[o << 1 | 1])
            vis[o] = vis[o << 1];
        else vis[o] = vis[o << 1 | 1];
    
    }
    void query(int l, int r, int o, int ql, int qr, int k){
        if (l == r){
            if (tree[o]>k)
                cur = min(cur, l);
            return;
        }
        int m = (l + r) >> 1;
        if (l >= ql&&r <= qr){
            if (tree[o << 1] > k)
                query(lson, ql, qr, k);
            else if (tree[o << 1 | 1] > k)
                query(rson, ql, qr, k);
            return;
        }
        if (ql <= m)
            query(lson, ql, qr, k);
        if (qr > m)query(rson, ql, qr, k);
    }
    void query1(int l, int r, int o, int ql, int qr){
        if (l >= ql&&r <= qr){
            if (tree[o] > a[cur])
                cur = vis[o];
            return;
        }
        int m = (l + r) >> 1;
        if (ql <= m)query1(lson, ql, qr);
        if (qr > m)query1(rson, ql, qr);
    }
    int main(){
        ios::sync_with_stdio(false);
    
        int t; cin >> t;
        while (t--){
            int n, m, p, q, Max = 0;
            cin >> n >> m;
            for (int i = 1; i <= n; i++){
                cin >> a[i];
                if (a[i] > Max)
                    d1[i] = d1[i - 1] + 1, Max = a[i];
                else d1[i] = d1[i - 1];
            }
            build(1, n, 1);
            for (int i = n; i; i--){
                cur = n + 1;
                query(1, n, 1, i, n, a[i]);
                if (cur > n)cur = 0;
                d2[i] = d2[cur] + 1;
            }
            while (m--){
                cin >> p >> q;
                ans = cur = 0;
                if (p != 1){
                    query1(1, n, 1, 1, p - 1);
                }
                ans += d1[cur];
                if (q > a[cur])ans++;
                else q = a[cur];
                cur = n + 1;
    
                if (p != n)query(1, n, 1, p + 1, n, q);
                if (cur <= n)ans += d2[cur];
                cout << ans << endl;
            }
        }
    }
  • 相关阅读:
    Python函数高级
    Python 2和3的区别
    GIL,python全局解释器锁
    Python中的 list
    python中的单例
    新式类和经典类
    整理的排序算法
    Python的双下划方法
    Python 中闭包函数和装饰器
    面向对象,特性之继承
  • 原文地址:https://www.cnblogs.com/zengguoqiang/p/9506601.html
Copyright © 2020-2023  润新知