codeforces 2057D. Gifts Order
题目大意
给定一个长度为n数组 an
设l~r的最大价值为
m a x ( a l , a l + 1 , . . . , a r ) − m i n ( a l , a l + 1 , . . . , a r ) − ( r − l ) max(a_l,a_{l+1},...,ar)-min(a_l,a_{l+1},...,ar)-(r-l) max(al,al+1,...,ar)−min(al,al+1,...,ar)−(r−l)
共有两种操作,一是给你位置p和值x,修改第p个位置的值为x
第二是an数组中选择一个l,r,使得l~r为数组的最大价值
思路
分析一下,当最大值在左边,最小值在右边时,式子可变为 ( a l + l ) − ( a r + r ) (a_l+l)-(a_r+r) (al+l)−(ar+r),相反则为 ( a r − r ) − ( a l − l ) (a_r-r)-(a_l-l) (ar−r)−(al−l)
所以针对两种情况我们可以化简为 a i + i a_i+i ai+i和 a i − i a_i-i ai−i
维护每个区间的两种情况的最大值最小值
区间(1~n)查询和单点修改,可以用线段树来解决,
设数组tr,第一维度 0 代表 a l > a r , 1 代表 a l < = a r 0代表al>ar,1代表al<=ar 0代表al>ar,1代表al<=ar
第二维0代表区间最小值,1代表区间最大值,val数组代表当前节点的最大价值
在pushup操作求节点最大值时,可以是两个子节点的最大值,也可以是以下两种情况
当 a l > a r a_l>a_r al>ar时(ai+i),即最大值在左边,最小值在右边,那么就用左边的最大值减去左边的最小值
当 a l < = a r a_l<=a_r al<=ar时(ai-i),即最大值在右边,最小值在左边的情况,就用右边的最大值减去左边的最小值
// Author: zengyz
// 2025-06-12 18:15#include <bits/stdc++.h>using namespace std;
using i64 = long long;
const int N = 2e5 + 10;
int tr[2][2][N * 4], val[N * 4];
int a[N];
void pushup(int u)
{tr[0][0][u] = min(tr[0][0][u << 1], tr[0][0][u << 1 | 1]);tr[0][1][u] = max(tr[0][1][u << 1], tr[0][1][u << 1 | 1]);tr[1][0][u] = min(tr[1][0][u << 1], tr[1][0][u << 1 | 1]);tr[1][1][u] = max(tr[1][1][u << 1], tr[1][1][u << 1 | 1]);val[u] = max(tr[0][1][u << 1] - tr[0][0][u << 1 | 1], tr[1][1][u << 1 | 1] - tr[1][0][u << 1]);val[u] = max(val[u], max(val[u << 1], val[u << 1 | 1]));
}
void build(int u, int l, int r)
{if (l == r){tr[0][0][u] = tr[0][1][u] = a[l] + l;tr[1][0][u] = tr[1][1][u] = a[l] - l;val[u] = 0;return;}else{int mid = (l + r) >> 1;build(u << 1, l, mid);build(u << 1 | 1, mid + 1, r);pushup(u);}
}
void modify(int u, int l, int r, int p, int x)
{if (l == r){tr[0][0][u] = tr[0][1][u] = x + p;tr[1][0][u] = tr[1][1][u] = x - p;return;}int mid = (l + r) >> 1;if (p <= mid)modify(u << 1, l, mid, p, x);elsemodify(u << 1 | 1, mid + 1, r, p, x);pushup(u);
}void solve()
{int n, q;cin >> n >> q;for (int i = 1; i <= n; i++)cin >> a[i];build(1, 1, n);cout << val[1] << endl;while (q--){int p, x;cin >> p >> x;a[p] = x;modify(1, 1, n, p, x);cout << val[1] << endl;}return;
}int main()
{ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int _T = 1;cin >> _T;while (_T--){solve();}return 0;
}