题解:历史最值线段树
参见吉司机的论文
还是不熟,自己打打不出来
维护当前和历史两套标记,最大值,加法标记,减法标记
每到一个节点先pushdown(不知道为什么)
正确性不是很理解QWQ
还是自己太弱了
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100009;
typedef long long Lint;
const Lint inf=1000000000000000;
int n,m;
Lint a[maxn];
struct SegmentTree{
int l,r;
Lint mx[2],tag[2],st[2];
}tree[maxn<<3];
void pushup(int now){
tree[now].mx[0]=max(tree[now<<1].mx[0],tree[now<<1|1].mx[0]);
tree[now].mx[1]=max(tree[now<<1].mx[1],tree[now<<1|1].mx[1]);
}
void pushdown(int now){
int son;
for(int i=0;i<=1;++i){
son=now<<1|i;
tree[son].mx[0]=max(tree[son].mx[0],max(tree[now].st[0],tree[son].mx[1]+tree[now].tag[0]));
if(tree[son].st[1]==-inf){
tree[son].tag[0]=max(tree[son].tag[0],tree[son].tag[1]+tree[now].tag[0]);
}else{
tree[son].st[0]=max(tree[son].st[0],tree[son].st[1]+tree[now].tag[0]);
}
if(tree[now].tag[1]){
if(tree[son].st[1]!=-inf)tree[son].st[1]+=tree[now].tag[1];
else tree[son].tag[1]+=tree[now].tag[1];
tree[son].mx[1]+=tree[now].tag[1];
}
if(tree[now].st[1]!=-inf){
tree[son].st[1]=tree[son].mx[1]=tree[now].st[1];
tree[son].tag[1]=0;
}
tree[son].st[0]=max(tree[son].st[0],max(tree[son].st[1],tree[now].st[0]));
tree[son].tag[0]=max(tree[son].tag[0],tree[son].tag[1]);
}
tree[now].tag[0]=tree[now].tag[1]=0;
tree[now].st[0]=tree[now].st[1]=-inf;
}
void BuildTree(int now,int l,int r){
tree[now].l=l;tree[now].r=r;
tree[now].tag[0]=tree[now].tag[1]=0;
tree[now].st[0]=tree[now].st[1]=-inf;
if(l==r){
tree[now].mx[0]=tree[now].mx[1]=a[l];
return;
}
int mid=(l+r)>>1;
BuildTree(now<<1,l,mid);
BuildTree(now<<1|1,mid+1,r);
pushup(now);
}
void Updatasec(int now,int ll,int rr,Lint x,int opty){
if(tree[now].l!=tree[now].r)pushdown(now);
if(tree[now].l>=ll&&tree[now].r<=rr){
if(opty==0){
tree[now].mx[1]+=x;tree[now].tag[1]+=x;tree[now].tag[0]=x;
}else{
tree[now].st[1]=tree[now].st[0]=tree[now].mx[1]=x;
}
tree[now].mx[0]=max(tree[now].mx[0],tree[now].mx[1]);
return;
}
int mid=(tree[now].l+tree[now].r)>>1;
if(ll<=mid)Updatasec(now<<1,ll,rr,x,opty);
if(rr>mid)Updatasec(now<<1|1,ll,rr,x,opty);
pushup(now);
}
Lint Querymax(int now,int ll,int rr,int opty){
if(tree[now].l!=tree[now].r)pushdown(now);
if(tree[now].l>=ll&&tree[now].r<=rr){
return tree[now].mx[opty];
}
Lint ans=-inf;
int mid=(tree[now].l+tree[now].r)>>1;
if(ll<=mid)ans=max(ans,Querymax(now<<1,ll,rr,opty));
if(rr>mid)ans=max(ans,Querymax(now<<1|1,ll,rr,opty));
return ans;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%lld",&a[i]);
BuildTree(1,1,n);
scanf("%d",&m);
while(m--){
char opty=getchar();
while(opty<'A'||opty>'Z')opty=getchar();
int l,r,x;
scanf("%d%d",&l,&r);
if(opty=='Q')printf("%lld\n",Querymax(1,l,r,1));
if(opty=='A')printf("%lld\n",Querymax(1,l,r,0));
if(opty=='P'){
scanf("%d",&x);Updatasec(1,l,r,x,0);
}
if(opty=='C'){
scanf("%d",&x);Updatasec(1,l,r,x,1);
}
}
return 0;
}