zoukankan      html  css  js  c++  java
  • HDU 3308 LCIS 线段树 区间更新

      题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3308

      题目描述: 有两种操作, U x y  , 第xth赋值为y 。Q x y , 查询区间x-y的最长连续上升子序列的长度L

      解题思路: 对于线段树不好的我依然好难.....有太多细节需要注意了....但是这是一道很好的题, 一段区间的L可能从三个地方来, 一种是中间, 一种是以左起点为开头的, 一种是以右起点结尾的, 这样查询的时候就要注意了: 如果两段的中间值是a[m] < a[m+1] 我们就要从这三段中选出一个最大的, 否则就只从前两段中选出最大的. .....然后向上更新的时候要注意: 如果左区间是一个整个的LCIS, 那我们就应该将左区间更新为左区间加上左儿子的右区间, 右区间同理, 我解释的比较拗口......其实这是很巧的 , 我们可以从第一步将数画在纸上构造一遍就会很清楚.....最后BUG当然是不能少的啦........我啥都缺, 就是不缺BUG

      代码: 

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <cstring>
    #include <iterator>
    #include <cmath>
    #include <algorithm>
    #include <stack>
    #include <deque>
    #include <map>
    #include <set>
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    #define mem0(a) memset(a,0,sizeof(a))
    #define sca(x) scanf("%d",&x)
    #define de printf("=======
    ")
    typedef long long ll;
    using namespace std;
    
    int n, mm, t;
    const int maxn = 1e5+10;
    int no[maxn<<2], ls[maxn<<2], rs[maxn<<2];
    int a[maxn];
    int x, y;
    
    inline void pushUp( int l, int r, int rt ) {
        int m = (l+r) >> 1;
        ls[rt] = ls[rt<<1];
        rs[rt] = rs[rt<<1|1];
        no[rt] = max( no[rt<<1], no[rt<<1|1] );
        if( a[m] < a[m+1] ) {
            if(ls[rt] == m-l+1) ls[rt] += ls[rt<<1|1];
            if(rs[rt] == r-m) rs[rt] += rs[rt<<1];
            no[rt] = max( no[rt], ls[rt<<1|1]+rs[rt<<1] );
        }
    }
    
    void build(int l, int r, int rt) {
        if( l == r ) {
            no[rt] = ls[rt] = rs[rt] = 1;
            return;
        }
        int m = (l+r) >> 1;
        build( lson );
        build( rson );
        pushUp(l, r, rt);
    }
    
    void update(int l, int r, int rt) {
        if( l == r ) return;
        int m = (l+r) >> 1;
        if( x <= m ) update(lson);
        else update(rson);
        pushUp(l, r, rt);
    }
    
    int query(int l, int r, int rt) {
    //    cout << l << " " << r << endl; cout << "rt: " << rt << endl;
        if( x <= l && r <= y ) return no[rt];
        int m = (l + r) >> 1;
        if( y <= m ) return query(lson);
    //    cout << "**" << endl;
        if( x > m ) return query(rson);
    
        int t1 = query(lson);
        int t2 = query(rson);
        int ans = max( t1, t2 );
        if( a[m] < a[m+1] ) {
    //        ans = max( ans, ls[rt<<1|1]+rs[rt<<1] );
            ans=max(ans,(min(ls[rt<<1|1],y-m)+min(rs[rt<<1],m+1-x)));
        }
        return ans;
    }
    
    
    int main() {
        sca(t);
        while( t-- ) {
            scanf( "%d%d", &n, &mm );
            for( int i = 1; i <= n; i++ ) {
                sca(a[i]);
            }
            build(1, n, 1);
            char op[5];
            while( mm-- ) {
                scanf( "%s%d%d", op, &x, &y );
                ++x;
                if( op[0] == 'U' ) {
                    a[x] = y;
                    update(1, n, 1);
                }
                else {
                    ++y;
                    printf( "%d
    ", query(1, n, 1) );
                }
            }
        }
        return 0;
    }
    View Code

      思考: 线段树是个大坑啊....自己挖的坑自己填吧.......看看剑指offer啥的吧....下午又是水课

  • 相关阅读:
    python自省函数getattr的用法
    python-mysqldb安装
    weblogic部署脚本
    netcat使用
    ssh批量互信脚本
    yum安装出错
    centos文件误删除恢复
    lamp php的ssl,ssh支持
    ssh免密码登陆
    python 学习笔记 四 条件, 循环以及其他
  • 原文地址:https://www.cnblogs.com/FriskyPuppy/p/7472987.html
Copyright © 2011-2022 走看看