题意:求连续上升子序列的长度。输入 n和m表示 序列的长度为(0--n-1);
然后输入 Q表示 查询(x,y)最长连续子序列的个数,输入U(表示将第x个数改成y);
思路:线段树的区间合并 lsum表示最左边的最长子序列的个数,rsum,表示区间最右边
最长子序列的个数,msum表示整个区间最长连续子序列的个数。
其余的照常区间合并
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 100010
int lsum[MAX*4];
int rsum[MAX*4];
int msum[MAX*4];
int array[MAX];
int n,m;
int g,x;
int x1,x2;
int max(int x,int y)
{
if(x<y) return y;
return x;
}
void pushup(int rt,int left,int right)
{
int mid=(left+right)/2;
int ll=mid-left+1;
int rl=right-mid;
lsum[rt]=lsum[rt*2];
rsum[rt]=rsum[rt*2+1];
msum[rt]=max(msum[rt*2],msum[rt*2+1]);
if(array[mid]<array[mid+1])//左区间的最后一个元素小于右区间的第一个元素。
{
if(lsum[rt]==ll) lsum[rt]+=lsum[rt*2+1];//左子树最左边的连续子序列的个数等于他区间的长度。那么就的加上右子树最最左边最长子序列的长度
if(rsum[rt]==rl) rsum[rt]+=rsum[rt*2];//同上面一样
msum[rt]=max(msum[rt],rsum[rt*2]+lsum[rt*2+1]);
}
}
void build(int rt,int left,int right)
{
if(left==right)
{
lsum[rt]=rsum[rt]=msum[rt]=1;
return ;
}
int mid=(left+right)/2;
build(rt*2,left,mid);
build(rt*2+1,mid+1,right);
pushup(rt,left,right);
}
void update(int rt,int left,int right)
{
if(left==right)
{
array[left]=g;//修改
return ;
}
int mid=(left+right)/2;
if(x<=mid) update(rt*2,left,mid);
else update(rt*2+1,mid+1,right);
pushup(rt,left,right);//合并
}
int query(int rt,int left,int right)
{ // printf("left=%d %d\n",left,right);
if(left>=x1&&right<=x2)
{
return msum[rt];
}
int mid=(left+right)/2;
if(x2<=mid) return query(rt*2,left,mid);//要查的区间在左子树
else if(x1>mid) return query(rt*2+1,mid+1,right);//要查的区间在右子树
//在两块区域 那最大值等于这个区间 在左字树最长连续子序列的个数和右边最长连续子序列的个数的最大值,如果 左区间最后一个
//小于右区间第一个元素,就是这三者的最大
int lll=query(rt*2,left,mid);
int rrr=query(rt*2+1,mid+1,right);
int ans=max(lll,rrr);
if(array[mid]<array[mid+1])
{
int xxx=rsum[rt*2];
int yyy=lsum[rt*2+1];
//左字树最右边连续子序列的个数不应改 大于 要查询的最左区间到左子树最最右区间的个数
if(xxx>mid-x1+1) xxx=mid-x1+1;
if(yyy>x2-mid) yyy=x2-mid;//右子树同理
ans=max(ans,xxx+yyy);
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&array[i]);
}
build(1,1,n);
char a[5];
for(int i=1;i<=m;i++)
{
scanf("%s",a);
if(a[0]=='Q')
{
scanf("%d %d",&x1,&x2);
x1++,x2++;
printf("%d\n",query(1,1,n));
}
else
{
int y;
scanf("%d %d",&x,&y);
x++;
g=y;
update(1,1,n);
}
}
}
}