1. 程式人生 > >[HDOJ3308]LCIS(線段樹,區間合並,新的代碼)

[HDOJ3308]LCIS(線段樹,區間合並,新的代碼)

最優解 tdi php %d bits 給定 namespace span const

題目鏈接: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\n", 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 }

[HDOJ3308]LCIS(線段樹,區間合並,新的代碼)