题解:P7402 [COCI 2020/2021 #5] Sjeckanje
Claire0918 · · 题解
先考虑没有修改怎么做。我们注意到每一段只有最大值和最小值是有用的,并且如果我们并没有将实际上最大的选作最大值,或没有选到正确的最小值,答案一定是不优的,于是我们考虑直接钦定一个位置是否是最大值或最小值,设
这显然可以用
于是我们考虑用线段树来维护。考虑区间加的意义,如果线段树上
这显然是可以打标记正常用线段树维护的了,时间复杂度
Code:
#include<bits/stdc++.h>
#define mem(a, v) memset(a, v, sizeof(a))
using namespace std;
const int maxn = 2e5 + 10;
int n, q;
int a[maxn];
namespace segtree{
struct Mat{
long long mat[3][3];
Mat(){
mem(mat, -0x3f);
}
inline Mat operator * (const Mat & other) const {
Mat res;
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
for (int k = 0; k < 3; k++){
res.mat[i][j] = max(res.mat[i][j], mat[i][k] + other.mat[k][j]);
}
}
}
return res;
}
} res;
struct{
int l, r;
long long tag;
Mat val;
} tree[maxn << 2];
inline void build(int index, int l, int r){
tree[index].l = l, tree[index].r = r;
if (l == r){
tree[index].val.mat[0][0] = tree[index].val.mat[1][1] = tree[index].val.mat[2][2] = 0;
return tree[index].val.mat[0][2] = tree[index].val.mat[1][0] = -a[l], tree[index].val.mat[0][1] = tree[index].val.mat[2][0] = a[l], void();
}
const int mid = l + r >> 1;
build(index << 1, l, mid), build(index << 1 | 1, mid + 1, r), tree[index].val = tree[index << 1].val * tree[index << 1 | 1].val;
}
inline void _add(int index, long long k){
tree[index].val.mat[1][0] -= k, tree[index].val.mat[0][2] -= k, tree[index].val.mat[2][0] += k, tree[index].val.mat[0][1] += k;
tree[index].val.mat[2][1] += k << 1, tree[index].val.mat[1][2] -= k << 1, tree[index].tag += k;
}
inline void pushdown(int index){
_add(index << 1, tree[index].tag), _add(index << 1 | 1, tree[index].tag), tree[index].tag = 0;
}
inline void add(int index, int l, int r, int k){
if (l <= tree[index].l && r >= tree[index].r){
return _add(index, k);
}
pushdown(index);
const int mid = tree[index].l + tree[index].r >> 1;
l <= mid && (add(index << 1, l, r, k), 1538), r > mid && (add(index << 1 | 1, l, r, k), 1538), tree[index].val = tree[index << 1].val * tree[index << 1 | 1].val;
}
}
using namespace segtree;
int main(){
scanf("%d %d", &n, &q);
for (int i = 1; i <= n; i++){
scanf("%d", &a[i]);
}
build(1, 1, n);
while (q--){
int l, r, k;
scanf("%d %d %d", &l, &r, &k), add(1, l, r, k), res = Mat(), res.mat[0][0] = 0, res = res * tree[1].val, printf("%lld\n", res.mat[0][0]);
}
return 0;
}