hdu3308 线段树——区间合并

更新一个点;

求某个区间的最长连续上升序列;

链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 #define maxn 100009
 5 #define mid int m=(l+r)>>1
 6 int num[maxn], lsum[maxn<<2], rsum[maxn<<2], msum[maxn<<2], n, m, p, v, a, b;
 7 void pushup(int o, int l, int r)
 8 {
 9     mid;
10     if (num[m] < num[m+1])
11     {
12         lsum[o] = (lsum[o<<1] == m+1-l) ? (m+1-l+lsum[o<<1|1]) : lsum[o<<1];
13         rsum[o] = (rsum[o<<1|1] == r-m) ? (r-m+rsum[o<<1]) : rsum[o<<1|1];
14         msum[o] = max(max(msum[o<<1], msum[o<<1|1]), lsum[o<<1|1] + rsum[o<<1]);
15     }
16     else lsum[o] = lsum[o<<1], rsum[o] = rsum[o<<1|1], msum[o] = max(msum[o<<1], msum[o<<1|1]);
17 }
18 void build(int o, int l, int r)
19 {
20     if (l == r) {lsum[o]= rsum[o] = msum[o] = 1; return;}
21     mid; build(o<<1, l, m), build(o<<1|1, m+1, r), pushup(o, l, r);
22 }
23 void update(int o, int l, int r)
24 {
25     if (l == r) {num[p] = v; return;}
26     mid; if (p <= m) update(o<<1, l, m); else update(o<<1|1, m+1, r); pushup(o, l, r);
27 }
28 int query(int o, int l, int r)
29 {
30     if (a <= l && b >= r) return msum[o];
31     mid; int ret = 0;
32     if (a <= m) ret = max(ret, query(o<<1, l, m)); if (b > m) ret = max(ret, query(o<<1|1, m+1, r));
33     if (num[m] < num[m+1]) ret = max(ret, min(m-a+1, rsum[o<<1])+min(b-m, lsum[o<<1|1])); return ret;
34 }
35 int main(void)
36 {
37     int t, n, m; char ch[5]; scanf("%d", &t);
38     while (t--)
39     {
40         scanf("%d%d", &n, &m); for (int i = 1; i <= n; scanf("%d", num+i++)); build(1, 1, n);
41         while (m--)
42         {
43             scanf("%s%d%d", ch, &a, &b); a++, b++;
44             if (ch[0] == 'Q') printf("%d\n", query(1, 1, n)); else p = a, v = b-1, update(1, 1, n);
45         }
46     }
47     return 0;
48 }

。。

posted on 2013-07-03 14:10  aries__liu  阅读(353)  评论(0编辑  收藏  举报