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<=10 5).
The next line has n integers(0<=val<=10 5).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=10 5)
OR
Q A B(0<=A<=B< n).
Each case starts with two integers n , m(0<n,m<=10 5).
The next line has n integers(0<=val<=10 5).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=10 5)
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
刚看完题以为跟前一题hotel一样都是区间合并,后来准备开始敲的时候发现还是跟那个题差很多,这个题需要做的是查询区间内最长的升序排列数,也就是需要比较左儿子的最右端值与右儿子的最左端值,也就是需要在结构体里面多加两个变量。还有一个需要注意的是这题是从0开始的,而我建立的树是从1开始的,所以更新和查询时的区间或点都应该加一。
#include <iostream>
#include<cstdio>
#include<algorithm>
#define lson id<<1
#define rson id<<1|1
using namespace std;
int a[100010];
struct node
{
int le,ri,lm,rm; //le是区间的左端,ri是区间的右端,lm是区间内左端的数值,rm是区间内右端的数值
int ls,rs,ms; //这个和hotel一样
}t[100010*4];
void pushup(int id)
{
t[id].ls=t[lson].ls;
t[id].rs=t[rson].rs;
t[id].lm=t[lson].lm;
t[id].rm=t[rson].rm;
t[id].ms=max(t[lson].ms,t[rson].ms); //首先是认为父节点的最大连续值是等于左儿子和右儿子的最大连续值中较大的值
if(t[lson].rm<t[rson].lm) //如果左儿子的右端数值小于右儿子的左端数值,那么父节点的左右开始以及整个区间的连续值都可能需要更新
{
int m=t[id].ri-t[id].le+1;
if(t[lson].ls==m-m/2)
t[id].ls+=t[rson].ls;
if(t[rson].rs==m/2)
t[id].rs+=t[lson].rs;
t[id].ms=max(t[id].ms,t[lson].rs+t[rson].ls);
}
}
void build(int id,int l,int r)
{
t[id].le=l;
t[id].ri=r;
if(l==r) {
t[id].lm=t[id].rm=a[l];
t[id].ls=t[id].rs=t[id].ms=1;
return ;
}
int m=(l+r)>>1;
build(lson,l,m);
build(rson,m+1,r);
pushup(id); //本来之前是写了一段的,后来写pushup时发现两端代码长得差不多,就去掉了改为pushup
}
void update(int id,int x,int y)
{
if(t[id].le==t[id].ri)
{
t[id].lm=t[id].rm=y;
return ;
}
int m=(t[id].le+t[id].ri)/2;
if(x<=m) update(lson,x,y);
else update(rson,x,y);
pushup(id);
}
int query(int id,int l,int r)
{
if(l<=t[id].le&&t[id].ri<=r)
return t[id].ms;
int m=(t[id].le+t[id].ri)/2;
int ret=0;
if(l<=m) ret=max(ret,query(lson,l,r)); //先往左儿子区间查找,更新ret
if(r>m) ret=max(ret,query(rson,l,r)); //左儿子查完后,往右儿子区间查找,更新ret
if(t[lson].rm<t[rson].lm) //当满足能合并的条件时
ret=max(ret,min(t[lson].rs,m-l+1)+min(t[rson].ls,r-m)); //左儿子的右开始连续不能大于所查区间在左儿子中所占的长度,右儿子的左开始连续不能大于所查区间在右儿子中所占的长度,在把两边合并起来与re比较t取较大值
return ret;
}
int main()
{
int n,m,c;
scanf("%d",&c);
while(c--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build(1,1,n);
for(int i=0;i<m;i++){
char b[2];
int x,y;
scanf("%s",b);
if(b[0]=='U')
{
scanf("%d%d",&x,&y);
update(1,x+1,y); //更新的点的位置也需要加一
}
else{
scanf("%d%d",&x,&y);
printf("%d\n",query(1,x+1,y+1)); //因为是从0开始,区间都需要加一
}
}
}
return 0;
}