Title:
l+1) * a − I = l Σ r ci − gap (L, R), where gap(l,r)=max i=l+1r(di − di − 1) 2gap (L, R) = \ Max \ limits {I = L + 1} ^ R (D_ i-d_{i-1})^2gap(l,r)=i=l+1maxr(di−di−1)2. (n≤3×105)(n \leq 3×10^5)(n≤3×105)
Links:
https://codeforces.com/contest/1107/problem/G
Solutions:
In this paper, the author analyzes the characteristics of ], query the largest sum[r]sum[r]sum[r] on the right, and then subtract the smallest sum[l]sum[l]sum[l] on the left to get the maximum interval (or processing prefix and suffix sum) across the gap gap.
Reference code:
Sorting + parallel query + line tree:
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int, int> pii; #define sz(a) ((int)a.size()) #define pb push_back #define lson (rt << 1) #define rson (rt << 1 | 1) #define gmid (l + r >> 1) const int maxn = 3e5 + 5; const int inf = 0x3f3f3f3f; const int mod = 1e9 + 7; typedef pair<ll, int> pli; const ll oo = 1ll << 60; pli tp[maxn]; ll d[maxn], c[maxn], sum[maxn]; int pre[maxn], li[maxn], ri[maxn]; int n, A; ll ans; struct SegTree{ ll mx[maxn << 2], add[maxn << 2]; void pushUp(int rt){ mx[rt] = max(mx[lson], mx[rson]); } void build(int l, int r, int rt){ add[rt] = 0; if(l == r){ mx[rt] = A - c[l]; return; } int mid = gmid; build(l, mid, lson); build(mid + 1, r, rson); pushUp(rt); } void pushDown(int rt){ if(add[rt]){ add[lson] += add[rt], add[rson] += add[rt]; mx[lson] += add[rt], mx[rson] += add[rt]; add[rt] = 0; } } void update(int l, int r, int rt, int L, int R, ll val){ if(l >= L && r <= R){ add[rt] += val, mx[rt] += val; return; } int mid = gmid; pushDown(rt); if(L <= mid) update(l, mid, lson, L, R, val); if(R > mid) update(mid + 1, r, rson, L, R, val); pushUp(rt); } ll query(int l, int r, int rt, int L, int R){ if(l >= L && r <= R) return mx[rt]; int mid = gmid; ll ret = -oo; pushDown(rt); if(L <= mid) ret = max(ret, query(l, mid, lson, L, R)); if(R > mid) ret = max(ret, query(mid + 1, r, rson, L, R)); return ret; } } trL, trR; int fin(int x){ return x == pre[x] ? x : pre[x] = fin(pre[x]); } void merge(int x, int y, ll D){ int fx = fin(x), fy = fin(y); if(fx == fy) return; int l1 = li[fx], r1 = ri[fx]; int l2 = li[fy], r2 = ri[fy]; ll mxL = trL.query(1, n, 1, l1, r1); ll mxR = trR.query(1, n, 1, l2, r2); // cout << x << " " << y << " " << D << " " << mxL << " " << mxR << endl; ans = max(ans, mxL + mxR - D); trL.update(1, n, 1, l1, r1, sum[fy]); trR.update(1, n, 1, l2, r2, sum[fx]); li[fx] = min(li[fx], li[fy]); ri[fx] = max(ri[fx], ri[fy]); sum[fx] += sum[fy]; pre[fy] = fx; } int main(){ ios::sync_with_stdio(0); cin.tie(0); cin >> n >> A; for(int i = 1; i <= n; ++i) cin >> d[i] >> c[i]; for(int i = 2; i <= n; ++i){ tp[i] = {(d[i] - d[i - 1]) * (d[i] - d[i - 1]), i}; } sort(tp + 2, tp + 1 + n); for(int i = 1; i <= n; ++i){ pre[i] = li[i] = ri[i] = i; sum[i] = A - c[i]; ans = max(ans, sum[i]); } trL.build(1, n, 1), trR.build(1, n, 1); for(int i = 2; i <= n; ++i){ int y = tp[i].second, x = y - 1; merge(x, y, tp[i].first); } cout << ans << endl; return 0; }
Monotone stack + RMQ:
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int, int> pii; #define sz(a) ((int)a.size()) #define pb push_back #define lson (rt << 1) #define rson (rt << 1 | 1) #define gmid (l + r >> 1) const int maxn = 3e5 + 5; const int inf = 0x3f3f3f3f; const int mod = 1e9 + 7; ll d[maxn], c[maxn]; int li[maxn], ri[maxn], stk[maxn]; int n, A, top; struct RMQ{ ll mn[maxn][21], mx[maxn][21]; int lg[maxn]; void build(){ lg[1] = 0; for(int i = 2; i <= n; ++i) lg[i] = lg[i >> 1] + 1; for(int i = 0; i <= n; ++i) mn[i][0] = mx[i][0] = c[i]; int k = lg[n]; for(int j = 1; j <= k; ++j){ for(int i = 0; i <= n; ++i){ if(i + (1 << j) - 1 > n) break; mn[i][j] = min(mn[i][j - 1], mn[i + (1 << (j - 1))][j - 1]); mx[i][j] = max(mx[i][j - 1], mx[i + (1 << (j - 1))][j - 1]); } } } ll query(int l, int r, int f){ int k = lg[r - l + 1]; if(f == 0) return min(mn[l][k], mn[r - (1 << k) + 1][k]); else return max(mx[l][k], mx[r - (1 << k) + 1][k]); } } rmq; int main(){ ios::sync_with_stdio(0); cin.tie(0); cin >> n >> A; for(int i = 1; i <= n; ++i) cin >> d[i] >> c[i]; for(int i = 1; i <= n; ++i){ c[i] = A - c[i]; c[i] += c[i - 1]; } for(int i = n; i >= 2; --i){ d[i] = (d[i] - d[i - 1]) * (d[i] - d[i - 1]); } top = 0, stk[0] = 1; for(int i = 2; i <= n; ++i){ while(top && d[i] >= d[stk[top]]) --top; li[i] = stk[top] + 1, stk[++top] = i; } top = 0, stk[0] = n + 1; for(int i = n; i >= 2; --i){ while(top && d[i] >= d[stk[top]]) --top; ri[i] = stk[top] - 1, stk[++top] = i; } for(int i = 2; i <= n; ++i) --li[i]; ll ret = 0; rmq.build(); for(int i = 1; i <= n; ++i) ret = max(ret, c[i] - c[i - 1]); for(int i = 2; i <= n; ++i){ ll tmx = rmq.query(i, ri[i], 1); ll tmn = rmq.query(li[i] - 1, i - 2, 0); // cout << i << " " << li[i] << " " << ri[i] << " " << tmx << " " << tmn << endl; ret = max(ret, tmx - tmn - d[i]); } cout << ret << endl; return 0; }