如果最后的表达式中,得到
k>s
,k表示斜率,s为某个数
那么我们就维护上凸包。
从左往右的上凸包
struct Point {
LL x, y;
Point() {}
Point(LL _x, LL _y) {
x = _x; y = _y;
}
Point operator-(const Point &P)const {
return Point(x - P.x, y - P.y);
}
LL operator*(const Point &P)const {
return x * P.y - y * P.x;
}
} P[MX], W[MX];
LL A[MX];
int n, sz;
LL solve() {
LL ret = 0; sz = 0;
for(int i = 1; i <= n; i++) {
while(sz >= 2 && (P[i] - W[sz]) * (W[sz] - W[sz - 1]) <= 0) sz--;
W[++sz] = P[i];
int l = 1, r = sz, m1, m2;
while(l < r) {
m1 = (2 * l + r) / 3;
m2 = (l + 2 * r + 2) / 3;
if(f(i, W[m1].x) < f(i, W[m2].x)) l = m1 + 1;
else r = m2 - 1;
}
ret = max(ret, f(i, W[l].x));
}
}
从右往左的上凸包
for(int i = n; i >= 1; i--) {
while(sz >= 2 && (P[i] - W[sz]) * (W[sz] - W[sz - 1]) >= 0) sz--;
如果最后的表达式中,得到
k<s
,k表示斜率,s为某个数
那么我们就维护下凸包。
从左往右的下凸包
for(int i = 1; i <= n; i++) {
while(sz >= 2 && (P[i] - W[sz]) * (W[sz] - W[sz - 1]) >= 0) sz--;
从右往左的下凸包
for(int i = n; i >= 1; i--) {
while(sz >= 2 && (P[i] - W[sz]) * (W[sz] - W[sz - 1]) <= 0) sz--;
对于是处理前缀的情况,假如题目要求得到
max(S1[r]−S1[l−1]−(l−1)∗(S2[r]−S2[l−1])
设
l1<l2
,令
f(l1)<(l2)
,可以得到
S2[r]<((l2−1)S2[l2]−S1[l2−1])−((l1−1)S2[l1]−S1[l1−1])l2−l1
如果我们把点当作
(i,(i−1)∗S2[i−1]−S1[i−1])
,那么其实表达的意思就是,这个位置是我们选择的左区间l位置。
如果我们把点当作
(i,i∗S2[i]−S1[i])
,那么这个位置i代表的是
l−1
位置。
(终于能无脑写斜率优化了hhhh