HDU 3308 LCIS (线段树区间合并)
Posted Recoder
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3308 LCIS (线段树区间合并)相关的知识,希望对你有一定的参考价值。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308
题目很好懂,就是单点更新,然后求区间的最长上升子序列。
线段树区间合并问题,注意合并的条件是a[mid + 1] > a[mid],写的细心点就好了。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int MAXN = 1e5 + 5; 6 struct SegTree { 7 int l , r , lsum , sum , rsum; 8 }T[MAXN << 2]; 9 int a[MAXN]; 10 11 void pushup(int p) { 12 int ls = p << 1 , rs = (p << 1)|1 , mid = (T[p].r + T[p].l) >> 1; 13 T[p].lsum = T[ls].lsum , T[p].rsum = T[rs].rsum; 14 if(T[p].lsum == T[ls].r - T[ls].l + 1) { 15 T[p].lsum += (a[mid + 1] > a[mid] ? T[rs].lsum : 0); 16 } 17 if(T[p].rsum == T[rs].r - T[rs].l + 1) { 18 T[p].rsum += (a[mid + 1] > a[mid] ? T[ls].rsum : 0); 19 } 20 T[p].sum = max(T[ls].sum , T[rs].sum); 21 int temp = (a[mid + 1] > a[mid] ? T[ls].rsum + T[rs].lsum : 1); 22 T[p].sum = max(temp , T[p].sum); 23 } 24 25 void build(int p , int l , int r) { 26 int mid = (l + r) >> 1; 27 T[p].l = l , T[p].r = r; 28 if(l == r) { 29 T[p].lsum = T[p].rsum = T[p].sum = 1; 30 return ; 31 } 32 build(p << 1 , l , mid); 33 build((p << 1)|1 , mid + 1 , r); 34 pushup(p); 35 } 36 37 void updata(int p , int pos , int num) { 38 int mid = (T[p].l + T[p].r) >> 1; 39 if(T[p].l == T[p].r && T[p].l == pos) { 40 a[pos] = num; 41 return ; 42 } 43 if(pos <= mid) { 44 updata(p << 1 , pos , num); 45 } 46 else { 47 updata((p << 1)|1 , pos , num); 48 } 49 pushup(p); 50 } 51 52 int query(int p , int l , int r) { 53 int mid = (T[p].l + T[p].r) >> 1; 54 if(l == T[p].l && T[p].r == r) { 55 return T[p].sum; 56 } 57 if(r <= mid) { 58 return query(p << 1 , l , r); 59 } 60 else if(l > mid) { 61 return query((p << 1)|1 , l , r); 62 } 63 else { 64 return max((a[mid + 1] > a[mid] ? min(mid - l + 1 , T[p << 1].rsum) + min(T[(p << 1)|1].lsum , r - mid) : 1) , 65 max(query(p << 1 , l , mid) , query((p << 1)|1 , mid + 1 , r) ) ); 66 } 67 } 68 69 int main() 70 { 71 int t , n , m; 72 scanf("%d" , &t); 73 while(t--) { 74 scanf("%d %d" , &n , &m); 75 for(int i = 1 ; i <= n ; ++i) { 76 scanf("%d" , a + i); 77 } 78 build(1 , 1 , n); 79 char q[5]; 80 int l , r; 81 while(m--) { 82 scanf("%s %d %d" , q , &l , &r); 83 if(q[0] == ‘Q‘) { 84 printf("%d\n" , query(1 , l + 1 , r + 1)); 85 } 86 else { 87 updata(1 , l + 1 , r); 88 } 89 } 90 } 91 return 0; 92 }
以上是关于HDU 3308 LCIS (线段树区间合并)的主要内容,如果未能解决你的问题,请参考以下文章