题目大意:给出一个数列要求支持:查询区间最大值,查询区间历史最大值,区间加,区间修改
除了历史最值都是最裸的线段树…
如果上最裸的线段树维护这个东西,在标记下推的时候可能把最值直接推没了…
看看怎么维护这个最值
在每个线段树结点上多维护两个量:历史最大的加法标记,历史最大的修改标记
更新子结点的历史最大值:当前结点的历史加法;当前结点历史修改;子结点的当前最大值
更新子结点的历史加法:当前结点的历史加法;子结点的当前加法
更新子结点的历史修改:当前结点的当前覆盖;子结点的历史覆盖
其他的都正常更新就行…
0表示现在,1表示历史
#include
#include
#define N 100005
#define INF (1ll<<60)
using namespace std;
typedef long long LL;
struct Node {
Node* ch[2];
int l,r;
LL maxx[2],add_mark[2],change_mark[2];
Node() {}
Node(int _l,int _r):l(_l),r(_r) {
maxx[0]=maxx[1]=0;
add_mark[0]=add_mark[1]=0;
change_mark[0]=change_mark[1]=-INF;
}
void* operator new(size_t) {
static Node *C,*mempool;
if(mempool==C) mempool=(C=new Node[1<<20])+(1<<20);
return C++;
}
void add(int v) {
maxx[0]+=v;
if(change_mark[0]!=-INF) change_mark[0]+=v;
else add_mark[0]+=v;
add_mark[1]=max(add_mark[1],add_mark[0]);
maxx[1]=max(maxx[1],maxx[0]);
return ;
}
void change(int v) {
change_mark[0]=maxx[0]=v;
add_mark[0]=0;
change_mark[1]=max(change_mark[1],change_mark[0]);
maxx[1]=max(maxx[1],maxx[0]);
return ;
}
void pushdown() {
for(int i=0;i<2;++i) {
ch[i]->maxx[1]=max(ch[i]->maxx[1],max(change_mark[1],ch[i]->maxx[0]+add_mark[1]));
if(ch[i]->change_mark[0]==-INF) ch[i]->add_mark[1]=max(ch[i]->add_mark[1],ch[i]->add_mark[0]+add_mark[1]);
else ch[i]->change_mark[1]=max(ch[i]->change_mark[1],ch[i]->change_mark[0]+add_mark[1]);
if(add_mark[0]) ch[i]->add(add_mark[0]);
if(change_mark[0]!=-INF) ch[i]->change(change_mark[0]);
ch[i]->change_mark[1]=max(ch[i]->change_mark[1],change_mark[1]);
}
add_mark[0]=add_mark[1]=0;
change_mark[0]=change_mark[1]=-INF;
return ;
}
void maintain() {
maxx[0]=max(ch[0]->maxx[0],ch[1]->maxx[0]);
maxx[1]=max(ch[0]->maxx[1],ch[1]->maxx[1]);
return ;
}
}*root;
int n,m,a[N];
void init(Node*& o,int l,int r) {
o=new Node(l,r);
if(l==r) {
o->maxx[0]=o->maxx[1]=a[l];
return ;
}
int mid=l+r>>1;
init(o->ch[0],l,mid), init(o->ch[1],mid+1,r);
o->maintain();
return ;
}
LL Query(Node* o,int l,int r,int mode) {
if(o->l==l && o->r==r) return o->maxx[mode];
o->pushdown();
int mid=o->l+o->r>>1;
if(r<=mid) return Query(o->ch[0],l,r,mode);
if(l>mid) return Query(o->ch[1],l,r,mode);
return max(Query(o->ch[0],l,mid,mode),Query(o->ch[1],mid+1,r,mode));
}
void Modify(Node* o,int l,int r,int v,int mode) {
if(o->l==l && o->r==r) {
if(!mode) o->add(v);
else o->change(v);
return ;
}
o->pushdown();
int mid=o->l+o->r>>1;
if(r<=mid) Modify(o->ch[0],l,r,v,mode);
else if(l>mid) Modify(o->ch[1],l,r,v,mode);
else Modify(o->ch[0],l,mid,v,mode), Modify(o->ch[1],mid+1,r,v,mode);
o->maintain();
return ;
}
int main() {
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",a+i);
init(root,1,n);
for(scanf("%d",&m);m;m--) {
char mode[2];
int x,y,z;
scanf("%s%d%d",mode,&x,&y);
if(mode[0]=='Q') printf("%lld\n",Query(root,x,y,0));
if(mode[0]=='A') printf("%lld\n",Query(root,x,y,1));
if(mode[0]=='P') scanf("%d",&z), Modify(root,x,y,z,0);
if(mode[0]=='C') scanf("%d",&z), Modify(root,x,y,z,1);
}
return 0;
}