题意:
给你N个整数,有两种操作,
(1)”U A B”,表示把第A个数变成B。
(2)”Q A B”,表示查询区间[A,B]的最长连续上升序列。
分析:
明显是线段树的题。
lx表示区间左起最长连续上升序列的长度。
rx表示区间右起最长连续上升序列的长度。
mx表示区间最长连续上升序列的长度。
vl表示区间左端点的值。
vr表示区间右端点的值。
合并区间:
如果当前区间的左儿子的lx等于左儿子的区间长度,那么当前区间的lx还要加上右儿子的lx。维护当前区间的rx也是类似的,当前区间的mx除了在左右儿子的区间中的mx取一个最大值外,还要注意,如果左儿子的右端点小于右儿子的左端点那么当前区间的mx还有可能是左儿子的rx加上右儿子的lx。
查询:
如果查询的范围是在当前区间的左右儿子里,并且左儿子的右端点小于右儿子的左端点,那么不能直接取左儿子的rx加上右儿子的lx,因为有可能查询的范围的长度就已经小于左儿子的rx加上右儿子的lx,所以要加上一个判断。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100100;
int n,m,ans,x,y,z,a[N];
struct edge{int l,r,mx,lx,rx,vl,vr,len;}g[4*N];
char s[100];
void pushup(int rt)
{
g[rt].lx=g[2*rt].lx;
g[rt].rx=g[2*rt+1].rx;
g[rt].vl=g[2*rt].vl;
g[rt].vr=g[2*rt+1].vr;
g[rt].mx=max(g[2*rt].mx,g[2*rt+1].mx);
if (g[2*rt].vr<g[2*rt+1].vl)
{
if (g[2*rt].lx==g[2*rt].len)
g[rt].lx+=g[2*rt+1].lx;
if (g[2*rt+1].rx==g[2*rt+1].len)
g[rt].rx+=g[2*rt].rx;
g[rt].mx=max(g[rt].mx,g[2*rt].rx+g[2*rt+1].lx);
}
g[rt].mx=max(g[rt].mx,max(g[rt].lx,g[rt].rx));
}
void build(int rt,int l,int r)
{
g[rt].l=l;
g[rt].r=r;
g[rt].len=r-l+1;
if (l==r)
{
g[rt].vl=g[rt].vr=a[l];
g[rt].lx=g[rt].rx=g[rt].mx=1;
return;
}
int mid=(l+r)/2;
build(2*rt,l,mid);
build(2*rt+1,mid+1,r);
pushup(rt);
}
void update(int rt,int k,int val)
{
int l=g[rt].l,r=g[rt].r;
if (l==r)
{
g[rt].vl=g[rt].vr=val;
return;
}
int mid=(l+r)/2;
if (k<=mid)
update(2*rt,k,val); else
update(2*rt+1,k,val);
pushup(rt);
}
int query(int rt,int ll,int rr)
{
int l=g[rt].l,r=g[rt].r;
if (ll<=l && r<=rr)
return g[rt].mx;
int mid=(l+r)/2;
if (ll> mid)
return query(2*rt+1,ll,rr); else
if (rr<=mid)
return query(2*rt,ll,rr); else
{
int m1,m2,t1=0,t2=0;
m1=query(2*rt,ll,rr);
m2=query(2*rt+1,ll,rr);
if (g[2*rt].vr<g[2*rt+1].vl)
{
t1=min(mid-ll+1,g[2*rt].rx);
t2=min(rr-mid,g[2*rt+1].lx);
}
return max(max(m1,m2),t1+t2);
}
}
int main()
{
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",a+i);
build(1,1,n);
for (int i=1;i<=m;i++)
{
scanf("%s",s);
if (s[0]=='Q')
{
scanf("%d%d",&x,&y);x++,y++;
printf("%d\n",query(1,x,y));
} else
{
scanf("%d%d",&x,&y);x++;
update(1,x,y);
}
}
}
}