题目链接: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\n", query(a, b, 1));
91             }
92         }
93     }
94     return 0;
95 }

转载于:https://www.cnblogs.com/kirai/p/5951773.html

[HDOJ3308]LCIS(线段树,区间合并)相关推荐

  1. hdu.3308 LCIS(线段树,区间合并+单点更新)

    按照傻崽大神的线段树修炼路线,自己做的第二道区间合并的题. 问题比较简单明了,区间求最长连续上升子序列,但是是需要单点更新的 n个数, m组操作 Q A B 询问[A,B]区间的最长连续上升子序列: ...

  2. hdu 3308 LCIS 线段树 + 区间合并

    传送门 文章目录 题意: 思路: 题意: 思路: 日常水一篇题解. 带修改的求区间连续的递增序列,我们考虑用线段树维护. 直接维护mlenmlenmlen是区间最长的递增序列,lslsls是从左端点开 ...

  3. 树链剖分——线段树区间合并bzoj染色

    线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了.. 一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些 struct Seg ...

  4. SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并

    Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...

  5. Tunnel Warfare(HDU1540+线段树+区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540 题目: 题意:总共有n个村庄,有q次操作,每次操作分为摧毁一座村庄,修复一座村庄,和查询与询问的 ...

  6. CodeForces - 1539F Strange Array(线段树区间合并)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的序列,规定位置 iii 的贡献是:设 x=a[i]x=a[i]x=a[i],选择一个包含 iii 的区间 [l,r][l,r][l,r],将其中 ...

  7. 牛客 - 求函数(线段树+区间合并/线段树+矩阵维护)

    题目链接:点击查看 题目大意:现在有 n 个函数,每个函数都是诸如 f( x ) = k * x + b 的形式,只是每个函数的 k 和 b 都是相互独立的,现在给出两个操作: 1 pos k b:将 ...

  8. 2021牛客暑期多校训练营7 xay loves monotonicity 线段树区间合并

    传送门 文章目录 题意: 思路: 题意: 题面挺绕口的,还是看原题比较好. 大概的意思就是让你从给定的区间中选择一个以左端点为起点的一个上升子序列,让后将这些下标存下来,在bbb中将这些位置拿出来后, ...

  9. poj-3667(线段树区间合并)

    题目链接:传送门 参考文章:传送门 思路:线段树区间合并问题,每次查询到满足线段树的区间最左值,然后更新线段树. #include<iostream> #include<cstdio ...

  10. HDU3308 线段树区间合并

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 ,简单的线段树区间合并. 线段树的区间合并:一般是要求求最长连续区间,在PushUp()函数中实 ...

最新文章

  1. 关于Block的copy和循环引用的问题
  2. 收藏:用DE-9IM判断二维空间位置关系
  3. 使用AD5933测量元器件的谐振特性
  4. vs2013新建web项目异常 0x80070002 处理
  5. 大话西游维护完怎么刷服务器,大话西游2很实用:看高玩教你如何快速刷齐高端套装...
  6. 推荐“公主妄想症系列之二:第一次”
  7. 45岁,一个平凡大叔的异地打工生活
  8. dotNET:怎样处理程序中的异常(理论篇)?
  9. 2021年春季学期期末统.考试 公司概论 试题
  10. C++Builder STL 泛型
  11. Filter过滤器拦截方式
  12. mysql 事务原子性_数据库事务原子性、一致性是怎样实现的?
  13. 区块链 single共识
  14. Android自动化测试框架Robotium
  15. UninstallPKG 1.1.9 Mac卸载工具
  16. 弘辽科技:淘宝流量下滑了怎么办?淘宝流量下滑应对方法
  17. 数据分析实战——淘宝母婴用品购买情况
  18. 项目目标的SMART原则
  19. 电脑控制手机投屏同步声音
  20. python验证角谷_角谷猜想-随心随性无为而为-51CTO博客

热门文章

  1. python编程100行_自己动手写100行Python代码抢火车票!
  2. 禁用win10触摸屏手势_我才发现win10居然有这么多好用的功能
  3. 计算机硬件基础大纲,计算机硬件技术基础大纲_.doc
  4. java解码base64的png图片_使用PHP对图片进行base64编码和解码(png、jpg,声音、视频)...
  5. 2021年如何0基础拿下HCIE证书?
  6. 设置finder窗口大小_五个Finder技巧让你快速提高工作效率
  7. 5G 和云原生时代的技术下半场,视频化是最大最新的确定性
  8. 免费下载来自阿里巴巴 双11 的《云原生大规模应用落地指南》
  9. 从零入门 Serverless | 一文详解 Serverless 架构模式
  10. Knative 应用在阿里云容器服务上的最佳实践