该题有两种操作,a和q。
对于a,我们在每一个节点设计一个add标记。
对于q,首先我们在每个节点设计一个lcis代表该区间的最长上升子串。
显然,这个值和三个值有关。
1.左儿子的lcis
2.右儿子的lcis
3.左右儿子合并lcis
现在关键就是解决3,我们在每个节点设计四个值,left,right,lmost,rmost,
分别代表区间最左边的值,最右边的值,最左边的最长上升子串能到达的最右端,
最右边的最长上升子串能到达的最左端.那么3就能够解决了.只用判断lson的right
和rson的left的大小情况,如果可以合并,那么3求得的值就是rson.lmost-lson.rmost+1。
线段树功能:updata 成段更新,query 区间最值。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define lc l,m,index<<1
#define rc m+1,r,index<<1|1
#define N 100100
struct node
{
int add;
int lcis;
int left,right;
int lmost,rmost;
}seg[N<<2];
int n,q;
void pushup(int index,int m)
{
node& father=seg[index];
node& lson=seg[index<<1];
node& rson=seg[index<<1|1];
father.lcis=max(lson.lcis,rson.lcis);
father.left=lson.left;
father.right=rson.right;
father.lmost=lson.lmost;
father.rmost=rson.rmost;
if(lson.right<rson.left)
{
father.lcis=max(father.lcis,rson.lmost-lson.rmost+1);
if(father.lmost==m)father.lmost=rson.lmost;
if(father.rmost==m+1)father.rmost=lson.rmost;
}
}
void build(int l,int r,int index)
{
int m=(l+r)>>1;
seg[index].add=0;
if(l==r)
{
scanf("%d",&seg[index].left);
seg[index].right=seg[index].left;
seg[index].lcis=1;
seg[index].lmost=seg[index].rmost=l;
return;
}
build(lc);
build(rc);
pushup(index,m);
}
void pushdown(int index)
{
node& father=seg[index];
node& lson=seg[index<<1];
node& rson=seg[index<<1|1];
if(father.add)
{
lson.add+=father.add;
lson.left+=father.add;
lson.right+=father.add;
rson.add+=father.add;
rson.left+=father.add;
rson.right+=father.add;
father.add=0;
}
}
void updata(int L,int R,int num,int l,int r,int index)
{
int m=(l+r)>>1;
if (L == l && r == R)
{
seg[index].add+=num;
seg[index].left+=num;
seg[index].right+=num;
return;
}
pushdown(index);
if(R<=m)updata(L,R,num,lc);
else if(L>m)updata(L,R,num,rc);
else
{
updata(L,m,num,lc);
updata(m+1,R,num,rc);
}
pushup(index,m);
}
int query(int L,int R,int l,int r,int index)
{
int m=(l+r)>>1;
if (L == l && r == R)return seg[index].lcis;
pushdown(index);
if(R<=m)return query(L,R,lc);
else if(L>m)return query(L,R,rc);
else
{
int ret;
ret=max(query(L,m,lc),query(m+1,R,rc));
if(seg[index<<1].right<seg[index<<1|1].left)
{
ret=max(ret,min(seg[index<<1|1].lmost,R)-max(seg[index<<1].rmost,L)+1);
}
return ret;
}
}
int main()
{
int t,tcase=1,a,b,c;
char op[2];
scanf("%d",&t);
while(t--)
{
printf("Case #%d:\n",tcase++);
scanf("%d%d",&n,&q);
build(1,n,1);
while(q--)
{
scanf("%s%d%d",op,&a,&b);
if(op[0]=='a')
{
scanf("%d",&c);
updata(a,b,c,1,n,1);
}
else
{
printf("%d\n",query(a,b,1,n,1));
}
}
}
return 0;
}