题目链接: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 }