做法:这里的区间合并要考虑左区间的最右值和右区间的最右值,看两个区间是否可以靠相合形成一个新序列
#include<cstdio>
#include<cstring>
#define left l,m,x<<1
#define right m+1,r,x<<1|1
const int LMT=100003;
int msum[LMT<<2],lsum[LMT<<2],rsum[LMT<<2],rnum[LMT<<2],lnum[LMT<<2];
inline int max(int a,int b)
{
return a>b?a:b;
}
void init(void)
{
memset(msum,0,sizeof(msum));
memset(lsum,0,sizeof(lsum));
memset(rsum,0,sizeof(rsum));
memset(lnum,0,sizeof(lnum));
memset(rnum,0,sizeof(rnum));
}
void pushup(int x,int len)
{
lnum[x]=lnum[x<<1];rnum[x]=rnum[x<<1|1];
lsum[x]=lsum[x<<1];rsum[x]=rsum[x<<1|1];
if(lsum[x]==len-(len>>1)&&lnum[x<<1|1]>rnum[x<<1])
lsum[x]+=lsum[x<<1|1];
if(rsum[x]==len>>1&&lnum[x<<1|1]>rnum[x<<1])
rsum[x]+=rsum[x<<1];
msum[x]=max(msum[x<<1],msum[x<<1|1]);
if(rnum[x<<1]<lnum[x<<1|1])
msum[x]=max(msum[x],rsum[x<<1]+lsum[x<<1|1]);
}
void update(int op,int pos,int l,int r,int x)
{
if(l==r)
{
lnum[x]=rnum[x]=op;
msum[x]=lsum[x]=rsum[x]=1;
return;
}
//if(pos==6)printf("%d %d %d\n",l,r,x);
int m=(l+r)>>1;
if(pos<=m)update(op,pos,left);
if(pos>m)update(op,pos,right);
pushup(x,r-l+1);
}
void query(int num[3],int sum[3],int L,int R,int l,int r,int x)
{
if(L<=l&&r<=R)
{
num[0]=lnum[x];num[2]=rnum[x];
sum[0]=lsum[x];
sum[1]=msum[x];
sum[2]=rsum[x];
return;
}
int m=(l+r)>>1,nums[2][3],sums[2][3],len=r-l+1;
memset(nums,0,sizeof(nums));
memset(sums,0,sizeof(sums));
//printf("%d %d %d\n",l,r,x);
if(L<=m)query(nums[0],sums[0],L,R,left);
if(R>m)query(nums[1],sums[1],L,R,right);
num[0]=nums[0][0];num[2]=nums[1][2];
sum[0]=sums[0][0];sum[2]=sums[1][2];
if(sums[0][0]==len-(len>>1)&&nums[0][2]<nums[1][0])
sum[0]+=sums[1][0];
if(sums[1][2]==len>>1&&nums[0][2]<nums[1][0])
sum[2]+=sums[0][2];
sum[1]=max(sums[0][1],sums[1][1]);
if(nums[0][2]<nums[1][0])
sum[1]=max(sums[0][2]+sums[1][0],sum[1]);
}
int main(void)
{
int T,n,i,x,l,r,m,sum[3],num[3];
char ord;
scanf("%d",&T);
while(T--)
{
init();
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
scanf("%d",&x);
update(x,i,0,n-1,1);
}
while(m--)
{
ord=getchar();
while(ord!='U'&&ord!='Q')ord=getchar();
memset(sum,0,sizeof(sum));
memset(num,0,sizeof(num));
if(ord=='Q')
{
scanf("%d%d",&l,&r);
query(num,sum,l,r,0,n-1,1);
printf("%d\n",sum[1]);
}
else
{
scanf("%d%d",&l,&x);
update(x,l,0,n-1,1);
}
}
}
return 0;
}