• [HDOJ3308]LCIS(线段树,区间合并,新的代码)


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

    题意:给定n个数,两个操作:

    U A B:将位置A的数值改成B

    Q A B:查询[A,B]内最长连续上升子序列的长度。

    我认为当时的代码风格和现在的不一样(因为喜欢在Seg里存l和r的下标,然而根本不用),所以重写了一份,也算是复习了。

    pushup操作里是不需要根据seg[rt].ls和seg[rt].rs更新seg[rt].ms的,而是从左右儿子的ms更新,以及lrt的最右元素与rrt的最左元素满足上升关系时,将这lrt的rs和rrt的ls连起来。

    query的时候也会遇到合并的问题,所以要像pushup操作一样,把两部分加起来更新一下结果。

    query里除了判断上升关系,L <= mid && mid < R这个我认为也是必要的,但是似乎不加也过了,可能是因为假如不满足这个条件,那么最优解肯定不在这里。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define lrt rt << 1
     5 #define rrt rt << 1 | 1
     6 typedef struct Seg {
     7     int ls, rs, ms;
     8 }Seg;
     9 const int maxn = 100100;
    10 Seg seg[maxn<<2];
    11 int val[maxn];
    12 int n, q;
    13 char op[3];
    14 
    15 void pushup(int l, int r, int rt) {
    16     int mid = (l + r) >> 1;
    17     seg[rt].ls = seg[lrt].ls; seg[rt].rs = seg[rrt].rs;
    18     if(seg[rt].ls == mid - l + 1 && val[mid] < val[mid+1]) seg[rt].ls += seg[rrt].ls;
    19     if(seg[rt].rs == r - mid && val[mid] < val[mid+1]) seg[rt].rs += seg[lrt].rs;
    20     seg[rt].ms = max(seg[lrt].ms, seg[rrt].ms);
    21     if(val[mid] < val[mid+1]) seg[rt].ms = max(seg[rt].ms, seg[lrt].rs+seg[rrt].ls);
    22 }
    23 
    24 void build(int l, int r, int rt) {
    25     if(l == r) {
    26         seg[rt].ls = seg[rt].rs = seg[rt].ms = 1;
    27         return;
    28     }
    29     int mid = (l + r) >> 1;
    30     build(l, mid, lrt);
    31     build(mid+1, r, rrt);
    32     pushup(l, r, rt);
    33 }
    34 
    35 void update(int pos, int val, int l, int r, int rt) {
    36     if(l == r) {
    37         seg[rt].ls = seg[rt].rs = seg[rt].ms = 1;
    38         return;
    39     }
    40     int mid = (l + r) >> 1;
    41     if(pos <= mid) update(pos, val, l, mid, lrt);
    42     else update(pos, val, mid+1, r, rrt);
    43     pushup(l, r, rt);
    44 }
    45 
    46 int query(int L, int R, int l, int r, int rt) {
    47     if(L <= l && r <= R) return seg[rt].ms;
    48     int mid = (l + r) >> 1;
    49     int ret = 0;
    50     if(L <= mid) ret = max(ret, query(L, R, l, mid, lrt));
    51     if(mid < R) ret = max(ret, query(L, R, mid+1, r, rrt));
    52     if(L <= mid && mid < R && val[mid] < val[mid+1]) {
    53         ret = max(ret, min(seg[lrt].rs, mid-L+1)+min(seg[rrt].ls,R-mid));
    54     }
    55     return ret;
    56 }
    57 int main() {
    58     // freopen("in", "r", stdin);
    59     int T, a, b;
    60     scanf("%d", &T);
    61     while(T--) {
    62         scanf("%d%d",&n,&q);
    63         for(int i = 1; i <= n; i++) {
    64             scanf("%d", &val[i]);
    65         }
    66         build(1, n, 1);
    67         while(q--) {
    68             scanf("%s%d%d",op,&a,&b);
    69             a++;
    70             if(op[0] == 'Q') {
    71                 b++;
    72                 printf("%d
    ", query(a, b, 1, n, 1));
    73             }
    74             else {
    75                 val[a] = b;
    76                 update(a, b, 1, n, 1);
    77             }
    78         }
    79     }
    80     return 0;
    81 }
  • 相关阅读:
    十个html5代码片段,超实用,一定要收藏
    零基础学编程,我想给你这五条建议
    Java 程序员开发常用的工具(二)
    Java 程序员开发常用的工具(一)
    前端人才饱和?平均年薪25W难求优质程序员!
    java基础学习 了解这些很有必要
    初学HTML5技术开发笔记整理
    HTML5移动开发学习笔记之02-CH4-HTML5 Web表单
    web前端笔记之Web前端的安全与漏洞
    5.SSH 免密码登陆
  • 原文地址:https://www.cnblogs.com/kirai/p/6814877.html
Copyright © 2020-2023  润新知