题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3064
题目要求很简单,就是维护一个区间最大值和只保留节点最大值的区间最大值。比较麻烦的是带区间修改,普通的lazy_tag会使得第二项被漏算。所以我们需要修改一下lazy_tag,也就是维护一个add,add最大值,set,set最大值,lazy_set,lazy_add,具体的下放自己YY一下就可以写出来了。但真的很恶心,写了两遍才写过。。。
怎么感觉好像没什么好说的了。。。直接上代码吧:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long LL;
const int maxn = 100000+10;
int n,q;
int A[maxn];
LL M[maxn*4],Mu[maxn*4],set[maxn*4],add[maxn*4],set_M[maxn*4],add_M[maxn*4];
bool lazy1[maxn*4],lazy2[maxn*4];
void Update(int u) {
int lc = u<<1,rc = lc|1;
M[u] = max(M[lc],M[rc]);
Mu[u] = max(Mu[lc],Mu[rc]);
}
void Build(int u,int l,int r) {
if(l == r) {M[u] = Mu[u] = A[l];return;}
int mid = (l+r) >> 1;
Build(u<<1,l,mid);
Build(u<<1|1,mid+1,r);
Update(u);
}
void Make1(int u,LL w) {
if(lazy1[u]) {
set[u] += w;
set_M[u] = max(set[u],set_M[u]);
Mu[u] = max(Mu[u],set_M[u]);
}
else {
add[u] += w;
if(!lazy2[u])add_M[u] = w;
else add_M[u] = max(add_M[u],add[u]);
lazy2[u] = true;
Mu[u] = max(Mu[u],M[u]+w);
}
M[u] += w;
}
void Make1(int u,LL w,LL MM) {
if(lazy1[u]) {
set_M[u] = max(set_M[u],set[u]+MM);
set[u] += w;
Mu[u] = max(Mu[u],set_M[u]);
}
else {
if(lazy2[u])add_M[u] = max(add_M[u],add[u]+MM);
else add_M[u] = MM;
add[u] += w;
lazy2[u] = true;
Mu[u] = max(Mu[u],M[u]+MM);
}
M[u] += w;
}
void Make2(int u,LL w) {
if(lazy1[u]) {
set[u] = w;set_M[u] = max(set_M[u],set[u]);
}
else {
lazy1[u] = true;set[u] = set_M[u] = w;
}
M[u] = w;Mu[u] = max(Mu[u],w);
}
void Make2(int u,LL w,LL MM) {
if(lazy1[u])set_M[u] = max(set_M[u],MM);
else set_M[u] = MM;
set[u] = w;lazy1[u] = true;
Mu[u] = max(Mu[u],set_M[u]);
M[u] = w;
}
void pushdown(int u) {
int lc = u<<1,rc = lc|1;
if(lazy2[u]) {Make1(lc,add[u],add_M[u]);Make1(rc,add[u],add_M[u]);}
if(lazy1[u]) {Make2(lc,set[u],set_M[u]);Make2(rc,set[u],set_M[u]);}
lazy1[u] = lazy2[u] = set[u] = set_M[u] = add[u] = add_M[u] = 0;
}
void Add(int u,int l,int r,int L,int R,int w) {
if(l >= L && r <= R) {Make1(u,w);return;}
pushdown(u);
int mid = (l+r) >> 1;
if(L <= mid)Add(u<<1,l,mid,L,R,w);
if(R > mid)Add(u<<1|1,mid+1,r,L,R,w);
Update(u);
}
void Set(int u,int l,int r,int L,int R,int w) {
if(l >= L && r <= R) {Make2(u,w);return;}
pushdown(u);
int mid = (l+r) >> 1;
if(L <= mid)Set(u<<1,l,mid,L,R,w);
if(R > mid)Set(u<<1|1,mid+1,r,L,R,w);
Update(u);
}
LL query1(int u,int l,int r,int L,int R) {
if(l >= L && r <= R)return M[u];
pushdown(u);
int mid = (l+r) >> 1;
if(R <= mid)return query1(u<<1,l,mid,L,R);
if(L > mid)return query1(u<<1|1,mid+1,r,L,R);
return max(query1(u<<1,l,mid,L,R),query1(u<<1|1,mid+1,r,L,R));
}
LL query2(int u,int l,int r,int L,int R) {
if(l >= L && r <= R)return Mu[u];
pushdown(u);
int mid = (l+r) >> 1;
if(R <= mid)return query2(u<<1,l,mid,L,R);
if(L > mid)return query2(u<<1|1,mid+1,r,L,R);
return max(query2(u<<1,l,mid,L,R),query2(u<<1|1,mid+1,r,L,R));
}
char s[5];
int main() {
scanf("%d",&n);int a,b,c;
for(int i = 1; i <= n; i++) {
scanf("%d",&A[i]);
}
Build(1,1,n);
scanf("%d",&q);
for(int i = 1; i <= q; i++) {
scanf("%s",s);
if(s[0] == 'Q') {
scanf("%d%d",&a,&b);
printf("%lld\n",query1(1,1,n,a,b));
}
else if(s[0] == 'A') {
scanf("%d%d",&a,&b);
printf("%lld\n",query2(1,1,n,a,b));
}
else if(s[0] == 'P') {
scanf("%d%d%d",&a,&b,&c);Add(1,1,n,a,b,c);
}
else if(s[0] == 'C') {
scanf("%d%d%d",&a,&b,&c);Set(1,1,n,a,b,c);
}
}
return 0;
}