hdu3308—LCIS

Posted friend-a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu3308—LCIS相关的知识,希望对你有一定的参考价值。

题目链接

  http://hdu.hustoj.com/showproblem.php?pid=3308

问题描述
给出n个整数,有两种操作
1)U A B:用B取代第A个数(下标从0开始)
2)Q A B:输出在[A,B]中最长连续递增子序列的长度
分析
给出一个序列,两种操作,分别是单点更新值和查询区间的最长连续递增子序列长
度,典型的线段树问题
首先考虑线段树的节点需要记录哪些值:
1)包含左端点的最长连续递增子序列长度,记作pre[]
2)包含右端点的最长连续递增子序列长度,记作suf[]
3)整个区间的最长连续递增子序列长度,记作sub[]
每次pushUp都需要自下而上更新这三个值。
注意点:
对于左连续,既可以由左儿子的左连续得来,也可能包含右儿子的左连续,这就要判断左儿子的左连续是否覆盖了整个区间,并且左儿子的最右值小于右儿子的最左值。同理对于右连续也是一样的。
对于整个区间的LCIS,可能来源于左右儿子的最值(因为可能左儿子的最右值不小于右儿子的最左值),也可能来源于两个区间的中间部分。
代码

  1 #include<stdio.h>
  2 const int maxn = 100010;
  3 int n, m, x, y;
  4 char ch[5];
  5 int val[maxn], sub[maxn * 4], pre[maxn * 4], suf[maxn * 4];
  6 
  7 int max(int a, int b)
  8 {
  9     return a > b ? a : b;
 10 }
 11 int min(int a, int b)
 12 {
 13     return a < b ? a : b;
 14 }
 15 
 16 void pushUp(int rt, int l, int r)
 17 {
 18     int m = (l + r) / 2;
 19 
 20     sub[rt] = max(sub[rt * 2], sub[rt * 2 + 1]);
 21     if(val[m] < val[m + 1])
 22         sub[rt] = max(sub[rt], suf[rt * 2] + pre[rt * 2 + 1]);
 23 
 24     pre[rt] = pre[rt * 2];
 25     if(pre[rt] == m - l + 1 && val[m] < val[m + 1])
 26         pre[rt] += pre[rt * 2 + 1];
 27 
 28     suf[rt] = suf[rt * 2 + 1];
 29     if(suf[rt] == r - m && val[m] < val[m + 1])
 30         suf[rt] += suf[rt * 2];
 31 }
 32 
 33 void build(int rt, int l, int r)
 34 {
 35     if(l == r)
 36     {
 37         sub[rt] = pre[rt] = suf[rt] = 1;
 38         return;
 39     }
 40     int m = (l + r) / 2;
 41     build(rt * 2, l, m);
 42     build(rt * 2 + 1, m + 1, r);
 43     pushUp(rt, l, r);
 44 }
 45 
 46 void update(int rt, int l, int r)
 47 {
 48     if(l == r)
 49         return;
 50     int m = (l + r) / 2;
 51     if(x <= m)
 52         update(rt * 2, l, m);
 53     else
 54         update(rt * 2 + 1, m + 1, r);
 55     pushUp(rt, l, r);
 56 }
 57 
 58 int query(int rt, int l, int r)
 59 {
 60     if(x <= l && y >= r)
 61         return sub[rt];
 62     int m = (l + r) / 2;
 63     if(y <= m)
 64         return query(rt * 2, l, m);
 65     if(x > m)
 66         return query(rt * 2 + 1, m + 1, r);
 67     int ans = max(query(rt * 2, l, m), query(rt * 2 + 1, m + 1, r));
 68     if(val[m] < val[m + 1])
 69     {
 70         ans = max(ans, min(suf[rt * 2], m - x + 1) + min(pre[rt * 2 + 1], y - m));
 71     }
 72     return ans;
 73 }
 74 int main()
 75 {
 76     int t;
 77     scanf("%d", &t);
 78     while(t--)
 79     {
 80         scanf("%d%d", &n, &m);
 81         for(int i = 1; i <= n; i++)
 82             scanf("%d", &val[i]);
 83         build(1, 1, n);
 84         while(m--)
 85         {
 86             scanf("%s%d%d", ch, &x, &y);
 87             x += 1;    //下标:0 1
 88             if(ch[0] == U)
 89             {
 90                 val[x] = y;
 91                 update(1, 1, n);
 92             }
 93             else if(ch[0] == Q)
 94             {
 95                 y += 1;
 96                 printf("%d
", query(1, 1, n));
 97             }
 98         }
 99     }
100     return 0;
101 }

 

以上是关于hdu3308—LCIS的主要内容,如果未能解决你的问题,请参考以下文章

hdu--3308 LCIS(线段树+区间合并)

hdu3308—LCIS

HDU 3308 LCIS (经典区间合并)线段树

HDU 3308 LCIS (线段树区间合并)

解题报告hdu3308 LCIS

HDU 3308 LCIS 线段树 区间更新