zoukankan      html  css  js  c++  java
  • [HDOJ3308]LCIS(线段树,区间合并)

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

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

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

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

    注意到‘连续’一词,可以用线段树维护[L,R]区间内的LICS。

    定义结构Node,内部l,r为左右儿子的下标。ls,rs记录当前区间分别从左起和右起的LICS长度,s记录整个区间内的LICS长度。

    pushup:和一般的区间合并操作一样,但是要注意假如合并的左右子树中间有可能成为LICS的时候,要判断是否符合条件,即左起右边界和右起左边界是否满足严格的关系。

    update:更新节点的时候直接赋值,再更新到线段树上的操作也是很常规的。

    query:比较奇特,因为有左起右边界和右起左边界连接起来的情况,所以查询的时候不是缩小线段树规模,而是缩小查询规模来获得解。而且要注意[L,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 Node {
     7     int l, r;
     8     int ls, s, rs;
     9 }Node;
    10 const int maxn = 100100;
    11 char cmd[5];
    12 int n, q;
    13 int x[maxn];
    14 Node seg[maxn<<4];
    15 
    16 void pushUP(int rt, int len) {
    17   seg[rt].ls = seg[lrt].ls; seg[rt].rs = seg[rrt].rs;
    18   if(seg[rt].ls == len-len/2) {
    19     if(x[seg[lrt].r] < x[seg[rrt].l]) {
    20       seg[rt].ls += seg[rrt].ls;
    21     }
    22   }
    23   if(seg[rt].rs == len/2) {
    24     if(x[seg[lrt].r] < x[seg[rrt].l]) {
    25       seg[rt].rs += seg[lrt].rs;
    26     }
    27   }
    28   seg[rt].s = max(seg[lrt].s, seg[rrt].s);
    29   if(x[seg[lrt].r] < x[seg[rrt].l]) {
    30     seg[rt].s = max(seg[rt].s, seg[lrt].rs+seg[rrt].ls);
    31   }
    32 }
    33 
    34 void build(int l, int r, int rt) {
    35     seg[rt].l = l; seg[rt].r = r;
    36     if(l == r) {
    37     seg[rt].ls = seg[rt].rs = seg[rt].s = 1;
    38     return;
    39     }
    40     int mid = (l + r) >> 1;
    41   build(l, mid, lrt);
    42   build(mid+1, r, rrt);
    43   pushUP(rt, r-l+1);
    44 }
    45 
    46 void update(int L, int R, int rt) {
    47   if(L <= seg[rt].l && seg[rt].r <= R) {
    48     seg[rt].ls = seg[rt].rs = seg[rt].s = 1;
    49     return;
    50   }
    51   int mid = (seg[rt].l + seg[rt].r) >> 1;
    52   if(L <= mid) update(L, R, lrt);
    53   if(mid < R) update(L, R, rrt);
    54   pushUP(rt, seg[rt].r-seg[rt].l+1);
    55 }
    56 
    57 int query(int L, int R, int rt) {
    58   if(L == seg[rt].l && R == seg[rt].r) return seg[rt].s;
    59   int mid = (seg[rt].l + seg[rt].r) >> 1;
    60   if(mid >= R) return query(L, R, lrt);
    61   else if(mid + 1 <= L) return query(L, R, rrt);
    62   else {
    63     int tmp = max(query(L, mid, lrt), query(mid+1, R, rrt));
    64     if(x[seg[lrt].r] < x[seg[rrt].l]) {
    65       tmp = max(tmp, min(seg[lrt].rs, mid-L+1)+min(seg[rrt].ls, R-mid));
    66     }
    67     return tmp;
    68   }
    69 }
    70 
    71 int main() {
    72 //    freopen("in", "r", stdin);
    73     int T, a, b;
    74     scanf("%d", &T);
    75     while(T--) {
    76         scanf("%d %d", &n, &q);
    77         for(int i = 1; i <= n; i++) {
    78             scanf("%d", &x[i]);
    79         }
    80         build(1, n, 1);
    81         while(q--) {
    82             scanf("%s %d %d", cmd, &a, &b);
    83             a++;
    84             if(cmd[0] == 'U') {
    85                 x[a] = b;
    86         update(a, a, 1);
    87             }
    88             else {
    89                 b++;
    90         printf("%d
    ", query(a, b, 1));
    91             }
    92         }
    93     }
    94     return 0;
    95 }
  • 相关阅读:
    jdbc配置Spring
    zend studio报错
    phpStudy 5.5n +zendstudio12.5+xDebugger的配置
    一个关于finally和return的面试题
    进制详解
    设计模式--桥接(Bridge)模式
    Struts2中文件上传下载实例
    java int and Integer
    java面试题
    Python __slots__的使用
  • 原文地址:https://www.cnblogs.com/kirai/p/5951773.html
Copyright © 2011-2022 走看看