和hdu 3308差不多
多了pushudown来更新区间内的值
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 100005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct Tree{
int l,r;
int lazy;
int lsum,rsum,msum;//分别为左儿子最长子序列,右儿子最长子序列,最优子序列
int lnum,rnum;//最左值,最右值
}tree[maxn<<2];
int num[maxn];
void PushUp(int rt)
{
int l,r,m;
l=tree[rt].l;
r=tree[rt].r;
m=(l+r)>>1;
tree[rt].lnum=tree[rt<<1].lnum;
tree[rt].rnum=tree[rt<<1|1].rnum;
tree[rt].lsum=tree[rt<<1].lsum;
tree[rt].rsum=tree[rt<<1|1].rsum;
tree[rt].msum=max(tree[rt<<1].msum,tree[rt<<1|1].msum);
if(tree[rt<<1].rnum<tree[rt<<1|1].lnum){
if(tree[rt<<1].lsum==m-l+1)
tree[rt].lsum+=tree[rt<<1|1].lsum;
if(tree[rt<<1|1].rsum==r-m)
tree[rt].rsum+=tree[rt<<1].rsum;
tree[rt].msum=max(tree[rt].msum,tree[rt<<1].rsum+tree[rt<<1|1].lsum);
}
}
void PushDown(int rt)
{
if(tree[rt].lazy){
tree[rt<<1].lazy+=tree[rt].lazy;
tree[rt<<1].lnum+=tree[rt].lazy;
tree[rt<<1].rnum+=tree[rt].lazy;
tree[rt<<1|1].lazy+=tree[rt].lazy;
tree[rt<<1|1].lnum+=tree[rt].lazy;
tree[rt<<1|1].rnum+=tree[rt].lazy;
tree[rt].lazy=0;
}
}
void build(int l,int r ,int rt)
{
tree[rt].l=l;
tree[rt].r=r;
tree[rt].lazy=0;
if(l==r){
tree[rt].rnum=tree[rt].lnum=num[l];
tree[rt].msum=tree[rt].lsum=tree[rt].rsum=1;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int x,int y,int val,int rt){
int l,r;
l=tree[rt].l;
r=tree[rt].r;
if(x==l&&r==y){
tree[rt].lazy+=val;
tree[rt].lnum+=val;
tree[rt].rnum+=val;
return ;
}
PushDown(rt);
int m=(l+r)>>1;
if(x<=m) update(x,min(m,y),val,rt<<1);
if(y>m) update(max(m+1,x),y,val,rt<<1|1);
PushUp(rt);
}
int query(int x,int y,int rt)
{
int l,r;
l=tree[rt].l;
r=tree[rt].r;
if(l==x&&r==y){
return tree[rt].msum;
}
// PushDown(rt);
int m=(l+r)>>1;
int ans=0;
if(x<=m) ans=max(ans,query(x,min(m,y),rt<<1));
if(y>m) ans=max(ans,query(max(m+1,x),y,rt<<1|1));
if(tree[rt<<1].rnum<tree[rt<<1|1].lnum){
ans=max(ans,min(tree[rt<<1].rsum,m-x+1)+min(tree[rt<<1|1].lsum,y-m));
}
return ans;
}
int main()
{
// freopen("1.txt","r",stdin);
int T,n,m,ncase=1;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&num[i]);
build(1,n,1);
printf("Case #%d:\n",ncase++);
while(m--){
int a,b,c;
char s[10];
scanf("%s",s);
if(s[0]=='q'){
scanf("%d%d",&a,&b);
printf("%d\n",query(a,b,1));
}
else{
scanf("%d%d%d",&a,&b,&c);
update(a,b,c,1);
}
}
}
return 0;
}