[CF2057D] Gifts Order 题解
似乎是一个很典的套路。
我们注意到一个区间成为答案时,最值一定在端点处。
(如果不是,那么收缩一个一定更优)
于是我们就可以按照最值位置分类。
- 最大值在区间左边,最小值在区间右边:答案就是 \((a_l + l) - (a_r + r)\)。
- 最大值在区间右边,最小值在区间左边:答案就是 \((a_r - r) - (a_l - l)\)。
我们直接线段树维护 \(a_i + i\) 的最值和 \(a_i - i\) 的最值即可。
Q:算出来的和原式不等价,为什么是对的?
A:算的过程中相当于多包含了一些劣的情况,但是在取 \(\max\) 的过程中自动舍掉了,于是是对的。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define Linf 0x3f3f3f3f3f3f3f3f
#define pii pair<int, int>
#define all(v) v.begin(), v.end()
using namespace std;
//#define filename "xxx"
#define FileOperations() freopen(filename".in", "r", stdin), freopen(filename".out", "w", stdout)
#define multi_cases 1
namespace Traveller {
const int N = 2e5+2;
int n, q, a[N];
struct data {
int mx1, mx2, mn1, mn2;
int ans;
data() { }
data(int a, int b, int c, int d, int e = 0) : mx1(a), mx2(b), mn1(c), mn2(d), ans(e) { }
};
data operator + (data a, data b) {
int ans = max(max(a.ans, b.ans), max(a.mx1 - b.mn1, b.mx2 - a.mn2));
int mx1 = max(a.mx1, b.mx1);
int mx2 = max(a.mx2, b.mx2);
int mn1 = min(a.mn1, b.mn1);
int mn2 = min(a.mn2, b.mn2);
return data(mx1, mx2, mn1, mn2, ans);
}
data operator + (data a, int b) {
int mx1 = a.mx1 + b;
int mx2 = a.mx2 + b;
int mn1 = a.mn1 + b;
int mn2 = a.mn2 + b;
return data(mx1, mx2, mn1, mn2);
}
class SegmentTree {
public:
struct node {
node *l, *r;
data d;
void up() { d = l->d + r->d; }
} pool[N << 1], *tmp, *root;
node *newnode() {
tmp->l = tmp->r = NULL;
tmp->d = data();
return tmp++;
}
int l, r;
public:
void build(node *&p, int l, int r, int *a) {
p = newnode();
if(l == r) {
p->d = data(a[l] + l, a[l] - l, a[l] + l, a[l] - l);
return;
}
int mid = l + r >> 1;
build(p->l, l, mid, a);
build(p->r, mid+1, r, a);
p->up();
}
void update(node *p, int l, int r, int idx, int v, int *a) {
if(l == r) {
p->d = p->d + (v - a[l]);
a[l] = v;
return;
}
int mid = l + r >> 1;
if(mid >= idx) update(p->l, l, mid, idx, v, a);
else update(p->r, mid+1, r, idx, v, a);
p->up();
}
int query() { return root->d.ans; }
void build(int l, int r, int *a) {
tmp = pool;
this->l = l, this->r = r;
build(root, l, r, a);
}
void update(int idx, int v, int *a) { update(root, l, r, idx, v, a); }
} tr;
void main() {
cin >> n >> q;
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
tr.build(1, n, a);
printf("%d\n", tr.query());
for(int i = 1, idx, v; i <= q; ++i) {
scanf("%d%d", &idx, &v);
tr.update(idx, v, a);
printf("%d\n", tr.query());
}
}
}
signed main() {
#ifdef filename
FileOperations();
#endif
signed _ = 1;
#ifdef multi_cases
scanf("%d", &_);
#endif
while(_--) Traveller::main();
return 0;
}

浙公网安备 33010602011771号