题意
- 给你一个序列,支持区间加上一个数,区间减去一个数,区间赋值,单点查询,单点历史最大值查询。
首先发现三种操作可以转化为同样的形式,定义为区间加上后与取max的标记,那么区间加就是,区间减就是,区间赋值就是,这个标记合并也比较方便,在标记后加上这个标记就变成了。
这样子我们就能很方便实现单点查询了,但是单点历史最大值查询似乎不太好做,我们对于每个点维护一个历史最大值标记,分别表示作用在这上面的所有标记中的两维分别的历史最大值,意思就是两维并不需要在同一个时候打上这个标记,下放的时候把父亲的历史最大值标记直接给儿子就好了,因为在下放前的所有影响了父亲的标记一定会影响儿子,并且这些标记是在儿子标记确定好之后发生的,所以可以直接把历史最大值标记合并到儿子的当前标记上,复杂度。
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define mp make_pair
#define inf (0x3f3f3f3f)
#define mem(a, b) memset(a, b, sizeof(a))
#define Rep(i, a) for (int i = 0; i < a; ++ i)
#define For(i, a, b) for (int i = a; i <= b; ++ i)
#define FOR(i, a, b) for (int i = a; i >= b; -- i)
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
template<class T>inline T read(T &_) {
T __ = getchar(), ___ = 1; _ = 0;
for (; !isdigit(__); __ = getchar()) if (__ == '-') ___ = -1;
for (; isdigit(__); __ = getchar()) _ = (_ << 3) + (_ << 1) + (__ ^ 48);
return _ *= ___;
}
template<class T>inline bool chkmax(T &_, T __) { return _ < __ ? _ = __, 1 : 0; }
template<class T>inline bool chkmin(T &_, T __) { return _ > __ ? _ = __, 1 : 0; }
inline void proStatus() {
ifstream t("/proc/self/status");
cerr << string(istreambuf_iterator<char>(t), istreambuf_iterator<char>());
}
const ll INF = 1e18;
const int N = 5e5 + 7;
inline PLL Max(PLL x, PLL y) { return mp(max(x.x, y.x), max(x.y, y.y)); }
inline PLL Merge(PLL x, PLL y) { return mp(max(-INF, x.x + y.x), max(x.y + y.x, y.y)); }
inline void Chkmax(PLL &x, PLL y) { x = Max(x, y); }
struct Segment_Tree {
#define ls (bh << 1)
#define rs (ls | 1)
#define mid ((l + r) >> 1)
#define lson ls, l, mid
#define rson rs, mid + 1, r
int tag[N << 2];
PLL now[N << 2], his[N << 2];
void build(int bh, int l, int r) {
if (l ^ r) build(lson), build(rson);
else his[bh].x = read(now[bh].x);
}
void pushdown(int bh) {
for (int son = ls; son <= rs; ++ son) {
tag[son] = true;
his[son] = Max(his[son], Merge(now[son], his[bh]));
now[son] = Merge(now[son], now[bh]);
}
now[bh] = his[bh] = mp(0, tag[bh] = 0);
}
void update(int bh, int l, int r, int x, int y, PLL z) {
if (x <= l && r <= y) {
Chkmax(his[bh], now[bh] = Merge(now[bh], z));
tag[bh] = true;
}
else {
if (tag[bh]) pushdown(bh);
if (x <= mid) update(lson, x, y, z);
if (y > mid) update(rson, x, y, z);
}
}
int query(int bh, int l, int r, int x) {
if (l == r) return bh;
if (tag[bh]) pushdown(bh);
return x <= mid ? query(lson, x) : query(rson, x);
}
}T;
int main() {
#ifndef ONLINE_JUDGE
freopen("164.in", "r", stdin);
freopen("164.out", "w", stdout);
#endif
int n, m, opt, x, y, z;
read(n), read(m), T.build(1, 1, n);
For(i, 1, m) {
read(opt), read(x);
if (opt < 4) {
read(y), read(z);
if (opt == 1) T.update(1, 1, n, x, y, mp(z, 0));
if (opt == 2) T.update(1, 1, n, x, y, mp(-z, 0));
if (opt == 3) T.update(1, 1, n, x, y, mp(-INF, z));
}
else {
int bh = T.query(1, 1, n, x);
printf("%lld\n", opt < 5 ? max(T.now[bh].x, T.now[bh].y)
: max(T.his[bh].x, T.his[bh].y));
}
}
return 0;
}