做法:这里的区间合并要考虑左区间的最右值和右区间的最右值,看两个区间是否可以靠相合形成一个新序列
#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; }