LCIS
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2658 Accepted Submission(s): 1152
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].
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).
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/*思路:*/ #include<iostream> #include<cstdio> using namespace std; #define MAX 100000 typedef struct infor { int l,r; //l是左孩子,r是右孩子 int lnum,rnum; //lnum序列最左边的值,rnum序列最右边值 int len,llen,rlen; //llen从最左边开始的最长递增序列元素个数 //rlen..最右边........................ //最大递增序列值 }infor; infor t[4*MAX] ; int a[MAX + 1] ; int max(int b, int c) { return b>c?b:c ; } void up(int rt , int m , int lenl , int lenr ) { t[rt].len = max(t[rt*2].len ,t[rt*2 + 1].len); //中间的最长递增序列 t[rt].llen = t[rt*2].llen ; //左边的递增序列 t[rt].rlen = t[rt*2 + 1].rlen ; //右边的递增序列 if(t[rt*2].rnum < t[rt*2 + 1].lnum )//开始合并两个序列,如果第一个序列的最右边的元素小于第二个 //序列的最左边的首元素 { //分别更新中间,左边,右边的最长序列 t[rt].len = max(t[rt*2].rlen + t[rt*2 + 1 ].llen, t[rt].len ); if(t[rt*2].llen >= lenl ) t[rt].llen +=t[rt*2 + 1].llen ; if(t[rt*2 + 1].rlen >= lenr) t[rt].rlen +=t[rt*2].rlen ; } } void create(int rt, int l , int r) { t[rt].l = l ; t[rt].r = r ; if(l == r) { t[rt].lnum = a[l] ; t[rt].rnum = a[l] ; t[rt].len = 1 ; t[rt].llen = 1 ; t[rt].rlen = 1 ; return ; } int mid = (l + r) / 2; create(rt*2 , l , mid ); create(rt*2 + 1 , mid + 1 , r ); t[rt].lnum = t[rt*2].lnum ; t[rt].rnum = t[rt*2 + 1].rnum ; up(rt , mid , mid - l + 1 , r - mid ); } void update(int rt, int l, int r , int pos , int val) { if(t[rt].l == t[rt].r) { t[rt].lnum = val; t[rt].rnum = val; return ; } int mid = (t[rt].l + t[rt].r ) / 2 ; if(pos > mid ) update(rt*2 + 1 , mid + 1 , r , pos , val ); else update(rt*2 , l , mid , pos , val ); t[rt].lnum = t[rt*2].lnum ; t[rt].rnum = t[rt*2 + 1].rnum ; up( rt , mid , mid - l + 1 , r - mid ); } int min(int b,int c) { return b<c?b:c ; } int cal(int rt , int l , int r , int x , int y ) { if(x <= l && y >= r) return t[rt].len; int mid = (t[rt].l+t[rt].r)/2; if(x > mid ) return cal(rt*2 + 1 , mid +1 , r , x , y); else if(y <= mid) return cal(rt*2 , l ,mid , x , y); int ret=max(cal(rt*2 , l , mid , x , y ),cal(rt*2 + 1 , mid + 1 , r , x , y )); if(t[rt*2].rnum<t[rt*2 + 1].lnum ) /*下面那句的解释:min(y,mid+t[rt*2+1].llen)即取右边的最小值,同时因为是一个子区间,可能不会包含整个左递增区间 类似于 左边序列:1,2,3,4,5 右边序列:6,7,3,2,1,如果如果只取到右边第一位,那么最小就是y,如果取到右边第五个, 那么只能取到mid+t[tr*2+1].llen(因为要求递增),原理是这样*/ return ret = max(ret , min(y,mid+t[rt*2+1].llen)-max(x,mid-t[rt*2].rlen+1)+1); // return ret=max(ret , t[rt*2].rlen+t[rt*2+1].llen); return ret ; } int main() { int Case; scanf("%d",&Case); while(Case --) { int n , m , i ; scanf("%d %d",&n,&m); for( i = 0 ; i < n ; i ++) scanf("%d",&a[i]); create(1,0,n-1); while(m--) { char ch[12]; int x,y; scanf("%s %d %d",ch,&x,&y); if(ch[0]=='U') update(1,0,n-1,x,y); if(ch[0]=='Q') printf("%d\n",cal(1,0,n-1,x,y)); } } return 0; }