线段树的区间修改加查询区间最大值相信大家都熟悉了,但是,如何查询一个历史的最大值呢?
此模板单纯是自己写写的,在oj上没有找到,是bzoj3064的弱化版,那题还有一个区间赋值的操作,更加麻烦。
#include
using namespace std;
const int N=1e5+5;
int n,m,x,y,v;
int a[N];
char str[10];
struct node{int sum,max,tagsum,tagmax;}T[N<<2];
inline void pushdown(int k)
{
T[k<<1].max=max(T[k<<1].max,T[k<<1].sum+T[k].tagmax);
T[k<<1].sum+=T[k].tagsum;
T[k<<1].tagmax=max(T[k<<1].tagmax,T[k<<1].tagsum+T[k].tagmax);
T[k<<1].tagsum+=T[k].tagsum;
T[k<<1|1].max=max(T[k<<1|1].max,T[k<<1|1].sum+T[k].tagmax);
T[k<<1|1].sum+=T[k].tagsum;
T[k<<1|1].tagmax=max(T[k<<1|1].tagmax,T[k<<1|1].tagsum+T[k].tagmax);
T[k<<1|1].tagsum+=T[k].tagsum;
T[k].tagsum=0; T[k].tagmax=-2e9;
}
void change(int k,int l,int r,int qx,int qy,int v)
{
if (qx<=l && r<=qy)
{
T[k].sum+=v;
T[k].max=max(T[k].max,T[k].sum);
T[k].tagsum+=v;
T[k].tagmax=max(T[k].tagmax,T[k].tagsum);
return;
}
pushdown(k);
int mid=l+r>>1;
if (qx<=mid) change(k<<1,l,mid,qx,qy,v);
if (mid<qy) change(k<<1|1,mid+1,r,qx,qy,v);
T[k].sum=max(T[k<<1].sum,T[k<<1|1].sum);
T[k].max=max(T[k<<1].max,T[k<<1|1].max);
}
int query(int k,int l,int r,int qx,int qy)
{
if (qx<=l && r<=qy) return T[k].max;
pushdown(k);
int mid=l+r>>1;
int res=-2e9;
if (qx<=mid) res=max(res,query(k<<1,l,mid,qx,qy));
if (mid<qy) res=max(res,query(k<<1|1,mid+1,r,qx,qy));
return res;
}
int querynow(int k,int l,int r,int qx,int qy)
{
if (qx<=l && r<=qy) return T[k].sum;
pushdown(k);
int mid=l+r>>1;
int res=-2e9;
if (qx<=mid) res=max(res,querynow(k<<1,l,mid,qx,qy));
if (mid<qy) res=max(res,querynow(k<<1|1,mid+1,r,qx,qy));
return res;
}
int main(){
scanf("%d",&n);
for (register int i=1; i<=(n<<2); ++i) T[i].max=T[i].tagmax=-2e9;
for (register int i=1; i<=n; ++i) scanf("%d",&a[i]);
for (register int i=1; i<=n; ++i) change(1,1,n,i,i,a[i]);
scanf("%d",&m);
while (m--)
{
scanf("%s",str+1);
if (str[1]=='Q')
{
scanf("%d%d",&x,&y);
printf("%d\n",querynow(1,1,n,x,y));
}
if (str[1]=='A')
{
scanf("%d%d",&x,&y);
printf("%d\n",query(1,1,n,x,y));
}
if (str[1]=='P')
{
scanf("%d%d%d",&x,&y,&v);
change(1,1,n,x,y,v);
}
}
return 0;
}