• 5W次单点修改,求最长的连续上升子序列 HDU 3308


    题目大意:给你n个数,m个操作。

    有两种操作:

    1.U x y 将数组第x位变为y  

    2. Q x y 问数组第x位到第y位连续最长子序列的长度。

    对于每次询问,输出连续最长子序列的长度

    思路:用线段树维护上升序列,每个端点维护:左边连续递增的len,右边连续递增的len,中间连续递增的len,左边val,右边val,和目前的len。然后不断更新即可。

    注意:如果左区间的最右边的值小于右区间最左边的值,则有一个待定答案是左儿子的右区间+右儿子的左区间

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #pragma comment(linker,"/STACK:102400000,102400000")
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    /*
    ①记录本身内部的序列长度
    ②要将区间合并的时候,rightson的left区间和leftson的right区间判断条件以后再合并。
    如果合并区间是对于两端的值
    */
    const int maxn = 1e5 + 5;
    struct Tree{
        int leftlen, rightlen, midlen, leftval, rightval, len;
    }tree[maxn << 2];
    int n, m;
    
    inline void pushup(int o){
        int lb = o << 1, rb = o << 1 | 1;
        int lbval = tree[lb].rightval, rbval = tree[rb].leftval;
        bool flag = false;
        tree[o].midlen = max(tree[lb].rightlen, max(tree[rb].leftlen, max(tree[lb].midlen, tree[rb].midlen)));
        if (lbval < rbval) {
            flag = true;
            tree[o].midlen = max(tree[lb].rightlen + tree[rb].leftlen, tree[o].midlen);
        }
    
        tree[o].leftlen = tree[lb].leftlen;
        if (tree[lb].rightlen == tree[lb].len && flag) tree[o].leftlen = tree[o].midlen;
    
        tree[o].rightlen = tree[rb].rightlen;
        if (tree[rb].leftlen == tree[rb].len && flag) tree[o].rightlen = tree[o].midlen;
        tree[o].leftval = tree[lb].leftval, tree[o].rightval = tree[rb].rightval;
    }
    
    void buildtree(int l, int r, int o){
        tree[o].len = r - l + 1;
        if (l == r){
            int val; scanf("%d", &val);
            tree[o].leftlen = tree[o].rightlen = tree[o].midlen = 1;
            tree[o].leftval = tree[o].rightval = val;
            return ;
        }
        int mid = (l + r) / 2;
        if (l <= mid) buildtree(l, mid, o << 1);
        if (r > mid) buildtree(mid + 1, r, o << 1 | 1);
        pushup(o);
        //printf("l = %d r = %d leftlen = %d rightlen = %d midlen = %d
    ", l, r, tree[o].leftlen, tree[o].rightlen, tree[o].midlen);
    }
    
    void update(int pos, int val, int l, int r, int o){
        if (pos == l && pos == r){
            tree[o].leftval = tree[o].rightval = val; return ;
        }
        int mid = (l + r) / 2;
        if (pos <= mid) update(pos, val, l, mid, o << 1);
        if (pos > mid) update(pos, val, mid + 1, r, o << 1 | 1);
        pushup(o);
    }
    
    int query(int ql, int qr, int l, int r, int o){
        int ans = 1;
        if (ql <= l && qr >= r){
            ans = max(ans, max(tree[o].leftlen, max(tree[o].rightlen, tree[o].midlen)));
            return ans;
        }
        int mid = (l + r) / 2;
        int t1 = -1, t2 = -1;
        if (mid >= ql){
            t1 = query(ql, qr, l, mid, o << 1);
        }
        if (mid < qr){
            t2 = query(ql, qr, mid + 1, r, o << 1 | 1);
        }
        ans = max(ans, max(t1, t2));
        ///如果左区间的最右边的值小于右区间最左边的值,则有一个待定答案是左儿子的右区间+右儿子的左区间
        if (tree[o << 1].rightval < tree[o << 1 | 1].leftval && t1 > 0 && t2 > 0){
            t1 = min(tree[o << 1].rightlen, mid - ql + 1) + min(tree[o << 1 | 1].leftlen, qr - mid);
            ans = max(ans, t1);
        }
        return ans;
    }
    
    int main(){
        int t; cin >> t;
        while (t--){
            scanf("%d%d", &n, &m);
            buildtree(1, n, 1);
            for (int i = 1; i <= m; i++){
                char ch[2]; int a, b;
                scanf("%s%d%d", ch, &a, &b);
                if (ch[0] == 'U'){
                    update(a + 1, b, 1, n, 1);
                }
                else {
                    printf("%d
    ", query(a + 1, b + 1, 1, n, 1));
                }
            }
        }
        return 0;
    }
    View Code

    关键:

    感觉和以前的一题CF很像,忘了是哪里的了......

  • 相关阅读:
    socket的accept函数解析
    c socket(续)
    C socket指南
    网络字节序和本机字节序
    jar包
    RESTful API 设计指南[转]
    理解RESTful架构[转]
    c语言正则表达式
    Fedora设置中文
    创建框架结构的页面2
  • 原文地址:https://www.cnblogs.com/heimao5027/p/6358782.html
Copyright © 2020-2023  润新知