[HDOJ3308]LCIS(线段树,区间合并)
Posted tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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,内部ls,rs为左右儿子的下标。l,r记录当前区间分别从左起和右起的LICS长度,s记录整个区间内的LICS长度。
pushup:和一般的区间合并操作一样,但是要注意假如合并的左右子树中间有可能成为LICS的时候,要判断是否符合条件,即左起右边界和右起左边界是否满足严格的关系。
update:更新节点的时候直接赋值,再更新到线段树上的操作也是很常规的。
query:比较奇特,因为有左起右边界和右起左边界连接起来的情况,所以查询的时候不是缩小线段树规模,而是缩小查询规模来获得解。而且要注意[L,R]的边界问题。子树的范围未必恰好满足,可能会更长。
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <cassert> 8 #include <cstdio> 9 #include <bitset> 10 #include <vector> 11 #include <deque> 12 #include <queue> 13 #include <stack> 14 #include <ctime> 15 #include <set> 16 #include <map> 17 #include <cmath> 18 using namespace std; 19 20 #define lrt rt << 1 21 #define rrt rt << 1 | 1 22 const int maxn = 100050; 23 typedef struct Node { 24 int ls, rs; 25 int s, l, r; 26 }Node; 27 28 Node seg[maxn<<2]; 29 int n, q; 30 int seq[maxn]; 31 char cmd[3]; 32 33 34 void pushUP(int rt, int len) { 35 seg[rt].l = seg[lrt].l; 36 seg[rt].r = seg[rrt].r; 37 if(seg[rt].l == len-len/2) { 38 if(seq[seg[lrt].rs] < seq[seg[rrt].ls]) { 39 seg[rt].l += seg[rrt].l; 40 } 41 } 42 if(seg[rt].r == len/2) { 43 if(seq[seg[lrt].rs] < seq[seg[rrt].ls]) { 44 seg[rt].r += seg[lrt].r; 45 } 46 } 47 seg[rt].s = max(seg[lrt].s, seg[rrt].s); 48 if(seq[seg[lrt].rs] < seq[seg[rrt].ls]) { 49 seg[rt].s = max(seg[rt].s, seg[lrt].r+seg[rrt].l); 50 } 51 } 52 53 void build(int l, int r, int rt) { 54 seg[rt].ls = l; 55 seg[rt].rs = r; 56 if(l == r) { 57 seg[rt].l = seg[rt].r = seg[rt].s = 1; 58 return; 59 } 60 int mid = (l + r) >> 1; 61 build(l, mid, lrt); 62 build(mid+1, r, rrt); 63 pushUP(rt, seg[rt].rs-seg[rt].ls+1); 64 } 65 66 int query(int L, int R, int rt) { 67 if(L <= seg[rt].ls && seg[rt].rs <= R) return seg[rt].s; 68 int mid = (seg[rt].ls + seg[rt].rs) >> 1; 69 if(mid >= R) return query(L, R, lrt); 70 else if(mid + 1 <= L) return query(L, R, rrt); 71 else { 72 int tmp = max(query(L, mid, lrt), query(mid+1, R, rrt)); 73 if(seq[seg[lrt].rs] < seq[seg[rrt].ls]) { 74 tmp = max(tmp, min(seg[lrt].r,mid-L+1)+min(seg[rrt].l,R-mid)); 75 } 76 return tmp; 77 } 78 } 79 80 void update(int L, int R, int rt) { 81 if(L <= seg[rt].ls && seg[rt].rs <= R) { 82 seg[rt].l = seg[rt].r = seg[rt].s = 1; 83 return; 84 } 85 int mid = (seg[rt].ls + seg[rt].rs) >> 1; 86 if(mid >= L) update(L, R, lrt); 87 if(mid < R) update(L, R, rrt); 88 pushUP(rt, seg[rt].rs-seg[rt].ls+1); 89 } 90 91 int main() { 92 // freopen("in", "r", stdin); 93 int qaq, a, b; 94 scanf("%d", &qaq); 95 while(qaq--) { 96 scanf("%d %d", &n, &q); 97 for(int i = 1; i <= n; i++) { 98 scanf("%d", &seq[i]); 99 } 100 build(1, n, 1); 101 while(q--) { 102 scanf("%s %d %d",cmd,&a,&b); 103 a++; 104 if(cmd[0] == ‘Q‘) { 105 b++; 106 printf("%d\n", query(a, b, 1)); 107 } 108 else if(cmd[0] == ‘U‘) { 109 seq[a] = b; 110 update(a, a, 1); 111 } 112 } 113 } 114 return 0; 115 }
以上是关于[HDOJ3308]LCIS(线段树,区间合并)的主要内容,如果未能解决你的问题,请参考以下文章