LCIS

Problem Description

Given n integers.
You have two operations:
U A B: replace the Ath number by B. (index counting from 0)
Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b].

Input

T in the first line, indicating the case number.
Each case starts with two integers n , m(0<n,m<=105).
The next line has n integers(0<=val<=105).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=105)
OR
Q A B(0<=A<=B< n).

Output

For each Q, output the answer.

Sample Input

1
10 10
7 7 3 3 5 9 9 8 1 8 
Q 6 6
U 3 4
Q 0 1
Q 0 5
Q 4 7
Q 3 5
Q 0 2
Q 4 6
U 6 10
Q 0 9

Sample Output

1
1
4
2
3
1
2
5
 1 #define maxn 100005
 2 #include<algorithm>
 3 #include<cstdio>
 4 using namespace std;
 5 
 6 struct Node
 7 {
 8     int lm,mm,rm;//以左端点开始的LCIS,整个区间的LCIS,以右端点结尾的LCIS
 9     int left,right;//区间端点
10     int len()
11     {
12         return right-left+1;
13     }
14 } tree[maxn<<2];
15 int N,M,val[maxn];
16 
17 void maintain(int id)//根据左右孩子信息来更新自己
18 {
19     int mid=(tree[id].left+tree[id].right)>>1;
20     if(val[mid]<val[mid+1])//左右子树存在合并的个数
21     {
22         tree[id].lm=tree[id<<1].lm+(tree[id<<1].lm==tree[id<<1].len()?tree[id<<1|1].lm:0);
23         tree[id].rm=tree[id<<1|1].rm+(tree[id<<1|1].rm==tree[id<<1|1].len()?tree[id<<1].rm:0);
24         tree[id].mm=max(max(tree[id].lm,tree[id].rm),max(tree[id<<1].mm,tree[id<<1|1].mm));
25         tree[id].mm=max(tree[id].mm,tree[id<<1].rm+tree[id<<1|1].lm);
26     }
27     else
28     {
29         tree[id].lm=tree[id<<1].lm;
30         tree[id].rm=tree[id<<1|1].rm;
31         tree[id].mm=max(tree[id<<1].mm,tree[id<<1|1].mm);
32     }
33 }
34 void build(int id,int left,int right)
35 {
36     tree[id].left=left,tree[id].right=right;
37     if(left==right)
38     {
39         tree[id].lm=tree[id].mm=tree[id].rm=1;
40         return ;
41     }
42     if(right-left>0)
43     {
44         int mid=(left+right)>>1;
45         build(id<<1,left,mid);
46         build(id<<1|1,mid+1,right);
47     }
48     maintain(id);//根据左右孩子更新自己的区间信息LCIS
49 }
50 void update(int id,int left,int right,int va)//将区间[left,right]的值更新为va
51 {
52     if(tree[id].left==tree[id].right)
53     {
54         val[left]=va;
55         return;
56     }
57     int mid=(tree[id].left+tree[id].right)>>1;
58     if(right<=mid) update(id<<1,left,right,va);
59     else update(id<<1|1,left,right,va);
60     maintain(id);
61 }
62 int query(int id,int left,int right)//查找区间[left,right]内的LCIS
63 {
64     if(left==tree[id].left&&right==tree[id].right) return tree[id].mm;
65     int mid=(tree[id].left+tree[id].right)>>1;
66     if(right<=mid) return query(id<<1,left,right);
67     else if(left>mid) return query(id<<1|1,left,right);
68     else
69     {
70         int mm=max(query(id<<1,left,mid),query(id<<1|1,mid+1,right));
71         if(val[mid]<val[mid+1])
72             //tree[id<<1].rm是tree[id<<1]所代表区间的rm,可能会大于[left,mid]区间的总长度,同理另一边
73             mm=max(mm,min(mid-left+1,tree[id<<1].rm)+min(right-mid,tree[id<<1|1].lm));
74         return mm;
75     }
76 }
77 
78 int main()
79 {
80     //freopen("in.txt","r",stdin);
81     int cases,a,b,i;
82     char op;
83     scanf("%d",&cases);
84     while(cases--)
85     {
86         scanf("%d%d",&N,&M);
87         for(i=1; i<=N; i++) scanf("%d",&val[i]);
88         build(1,0,N);
89         for(i=0; i<M; i++)
90         {
91             scanf("%s%d%d",&op,&a,&b);
92             if(op=='Q') a++,b++,printf("%d\n",query(1,a,b));
93             else a++,update(1,a,a,b);
94         }
95     }
96     return 0;
97 }
线段树(区间维护连续递增子序列最长个数)

 

posted @ 2013-08-19 17:08  1002liu  阅读(8984)  评论(0编辑  收藏  举报