我的做法大致思路是这样:
现在考虑定一个右端点 nowr,定义线段树中节点 [l,l] 表示的是区间 [l,nowr] 的答案。
每次右移的时候相当于插入一个 (dnowr+1−dnowr)2并且对于每一个 1 ~ nowr 的对应答案点的答案加上 a−P[nowr+1].c。
固定右端点的情况下,越往左边则 i=lmaxi=nowr−1(di+1−di)2 越小,于是可以在线段树上二分,动态维护答案最大值。
但是本辣鸡一直 WA on test 7。
希望有大佬告诉我这个方法的错误或者代码的错误,亦或者是提供一下 Hack 数据,感激不尽!
#include <bits/stdc++.h>
using namespace std;
#define ls (x << 1)
#define rs (x << 1 | 1)
#define mid ((T[x].l + T[x].r) >> 1)
#define int long long
inline int read() {
int x = 0, flag = 1;
char ch = getchar();
for( ; ch > '9' || ch < '0' ; ch = getchar()) if(ch == '-') flag = -1;
for( ; ch >= '0' && ch <= '9' ; ch = getchar()) x = (x << 3) + (x << 1) + ch - '0';
return x * flag;
}
int sqr(int a) { return 1ll * a * a ; }
const int MAXN = 3e5 + 50;
int n, V, m;
int Ans = 0;
struct Point {
int c, d;
} P[MAXN];
struct SegmentTree {
int l, r, Dmax, Dmin, Max, taga, tagb;
} T[MAXN << 2];
void update(int x) {
T[x].Max = max(T[ls].Max, T[rs].Max);
T[x].Dmax = max(T[ls].Dmax, T[rs].Dmax);
T[x].Dmin = min(T[ls].Dmin, T[rs].Dmin);
}
void build(int x, int l, int r) {
T[x].l = l, T[x].r = r, T[x].taga = T[x].tagb = 0;
if(l == r) return ;
build(ls, l, mid), build(rs, mid + 1, r);
return ;
}
void ad(int x, int M, int Add) {
T[x].Max += Add;
if(M >= T[x].Dmax) {
T[x].Max -= (sqr(M) - sqr(T[x].Dmax));
T[x].Dmin = T[x].Dmax = T[x].taga = M;
}
T[x].tagb += Add;
return ;
}
void pushdown(int x) {
ad(ls, T[x].taga, T[x].tagb);
ad(rs, T[x].taga, T[x].tagb);
T[x].taga = T[x].tagb = 0;
}
void change(int x, int l, int r, int k, int w) {
if(T[x].l >= l && T[x].r <= r) { ad(x, k, w); return ; }
pushdown(x);
if(l <= mid) change(ls, l, r, k, w);
if(r > mid) change(rs, l, r, k, w);
update(x);
}
void modify(int x, int l, int r, int k) {
if(l > r) return ;
if(T[x].l >= l && T[x].r <= r) {
if(T[x].Dmax <= k) { ad(x, k, 0); return ; }
if(T[x].l == T[x].r) return ;
pushdown(x);
if(k < T[x].Dmin) return ;
modify(ls, l, r, k), modify(rs, l, r, k), update(x);
return ;
}
pushdown(x);
if(l <= mid) modify(ls, l, r, k);
if(r > mid) modify(rs, l, r, k);
update(x);
return ;
}
signed main() {
n = read(), V = read(), build(1, 1, n);
for(int i = 1 ; i <= n ; i ++) P[i].d = read(), P[i].c = V - read();
for(int i = 1; i <= n ; i ++) {
change(1, 1, i, 0, P[i].c);
modify(1, 1, i - 1, P[i].d - P[i - 1].d);
Ans = max(Ans, T[1].Max);
}
cout << Ans;
return 0;
}