轉自:https://blog.csdn.net/lycheng1215/article/details/72790106?utm_source=blogxgwz2
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
using std::cin;
using std::cout;
using std::endl;
const int maxn=100005;
int tree[maxn*3];
int lazy[maxn*3];
int n,m;
void build(int node=1, int l=1, int r=n)
{
if(l==r)
{
scanf("%d",&tree[node]);
return;
}
int mid=(l+r)/2;
build(node<<1, l, mid);
build((node<<1)+1, mid+1, r);
tree[node]=std::max(tree[node<<1], tree[(node<<1)+1]);
}
void pushdown(int node)
{
if(lazy[node])
{
lazy[node<<1]+=lazy[node];
lazy[(node<<1)+1]+=lazy[node];
tree[node<<1]+=lazy[node];
tree[(node<<1)+1]+=lazy[node];
lazy[node]=0;
}
}
int g_L,g_R,g_Add;
void change(int node=1, int l=1, int r=n)
{
if(g_L<=l && r<=g_R)
{
tree[node]+=g_Add; //這個結點對應線段的所有點都加上了g_Add,所以最大值也加g_Add
lazy[node]+=g_Add; //我們只操作這個結點,而不遞歸傳下去,因爲這時我們傳下去了也用不到,所以通過lazy保存結點對應線段每個點的增加值
return;
}
int mid=(l+r)/2;
int lc=node<<1;
int rc=(node<<1)+1;
//現在要更新子結點了對吧,既然子結點的最大值還沒有加上g_Add,那我們怎麼知道加了後的值是多少呢?
pushdown(node); //那就更新它,把lazy記號推下去
if(g_L<=mid)
change(lc, l, mid);
if(g_R>mid)
change(rc, mid+1, r);
tree[node]=std::max(tree[lc],tree[rc]); //記住要回來更新父結點
}
//使用g_L和g_R
int query(int node=1, int l=1, int r=n)
{
if(g_L<=l && r<=g_R)
{
return tree[node]; //注意tree[node]的含義:我們已經保證tree[node]已經更新,所以答案就是tree[node],不要再加上lazy[node],它是作用於子結點的
}
int mid=(l+r)/2;
int lc=node<<1;
int rc=(node<<1)+1;
pushdown(node); //查詢時也要更新,以把加上的值記錄在內
int ans=0x80000000;
if(g_L<=mid)
ans=std::max(ans, query(lc, l, mid));
if(g_R>mid)
ans=std::max(ans, query(rc, mid+1, r));
return ans;
}
int main()
{
scanf("%d",&n);
build();
scanf("%d",&m);
while(m--)
{
int operation, l, r, value;
scanf("%d%d%d", &operation, &l, &r);
if(operation==1)
{
scanf("%d", &value);
g_L=l;
g_R=r;
g_Add=value;
change();
}
else if(operation==2)
{
g_L=l;
g_R=r;
printf("%d\n",query());
}
}
return 0;
}