题意:
求最长上升子序列的最大长度。
两种操作:
Q: 某一段区间的最长上升子序列的最大长度为多少
U: 某一点 = val
解题思路:
如果单单求最长上升子序列,我们可以通过dp,或者分治的思想来求。因为此处操作多,所以上述方法不可行。
我们在线段树的结点里增加几个域:
lsum : 表示从当前结点的最左端开始的上升子序列的长度
rsum: 表示从当前结点的最右端开始的上升子序列的长度
sum:表示当前结点上升子序列长度的最大值
所以在比较时:
同连续的区间一样 ,但要是递增的,所以左子树.rsum + 右子树.lsum
的前提条件是 左子树最右处的值要<右子树最左边的值
注意:
是递增的
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXN0 100010
#define l1(x) ((x)<<1)
#define r1(x) ((x)>>1)
struct TRnode{
int L,R;
int lsum,rsum,sum;
};
int val[MAXN0];
TRnode TR[MAXN0<<2];
int max(int aa,int bb){
return aa>bb?aa:bb;
}
void pu(int k,int k1,int k11){
int tmp0 = TR[k1].R - TR[k1].L + 1 ;
if(TR[k1].lsum == tmp0){
if(val[TR[k1].R]<val[TR[k11].L]){
TR[k].lsum = TR[k1].lsum + TR[k11].lsum;
}
else {
TR[k].lsum = TR[k1].lsum;
}
}
else {
TR[k].lsum = TR[k1].lsum;
}
tmp0 = TR[k11].R - TR[k11].L + 1;
if(tmp0==TR[k11].rsum){
if(val[TR[k1].R]<val[TR[k11].L]){
TR[k].rsum = TR[k11].rsum + TR[k1].rsum;
}
else {
TR[k].rsum = TR[k11].rsum;
}
}
else {
TR[k].rsum = TR[k11].rsum;
}
if(val[TR[k1].R]<val[TR[k11].L]){
tmp0 = TR[k1].rsum + TR[k11].lsum;
}
else {
tmp0 = max(TR[k1].rsum,TR[k11].lsum);
}
TR[k].sum = max(TR[k].rsum,TR[k].lsum);
TR[k].sum = max(TR[k].sum,tmp0);
TR[k].sum = max(max(TR[k1].sum,TR[k11].sum),TR[k].sum);
}
void buildTR(int L,int R,int k){
TR[k].L = L;
TR[k].R = R;
if(L==R){
TR[k].sum = TR[k].lsum = TR[k].rsum = 1;
return;
}
int mid = r1(L+R);
int k1,k11;
k1 = l1(k);
k11 = k1 + 1;
buildTR(L,mid,k1);
buildTR(mid+1,R,k11);
pu(k,k1,k11);
}
int query(int L,int R,int k){
if(TR[k].L==L&&TR[k].R==R){
return TR[k].sum;
}
int k1,k11;
k1 = l1(k);
k11 = k1 + 1 ;
int mid = r1(TR[k].L + TR[k].R);
if(mid>=R){
return query(L,R,k1);
}
else if(mid<L){
return query(L,R,k11);
}
else {
int tmp0,tmp1,tmp2,tmp3,tmp4,tmp5;
tmp0 = query(L,mid,k1);
tmp1 = query(mid+1,R,k11);
tmp2 = 0;
tmp3 = mid - L + 1;
tmp4 = R - mid;
tmp5 = 0;
if(TR[k1].rsum<=tmp3){
tmp3 = TR[k1].rsum;
}
if(TR[k11].lsum<=tmp4){
tmp4 = TR[k11].lsum;
}
if(val[TR[k1].R]<val[TR[k11].L]){
tmp2 = tmp3 + tmp4;
}
else {
tmp2 = max(tmp3,tmp4);
//tmp2 = max(TR[k1].rsum>=,TR[k11].lsum);
}
return max(tmp0,max(tmp1,tmp2));
}
}
void update(int A,int B,int k){
if(TR[k].L==TR[k].R){
TR[k].sum = TR[k].rsum = TR[k].lsum = 1;
val[TR[k].L] = B;
return;
}
int mid = r1(TR[k].L+TR[k].R);
int k1,k11;
k1 = l1(k);
k11 = k1 + 1;
if(mid>=A){
update(A,B,k1);
}
else {
update(A,B,k11);
}
pu(k,k1,k11);
}
int main(){
int n,m,A,B,ans;
char w[1];
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
scanf("%d",&val[i]);
}
buildTR(1, n, 1);
while(m--){
scanf("%s",w);
if(w[0]=='Q'){
scanf("%d%d",&A,&B);
++A;
++B;
int ans = query(A,B,1);
printf("%d\n",ans);
}
else {
scanf("%d%d",&A,&B);
++A;
update(A,B,1);
}
}
}
return 0;
}