CF660F Bear and Bowling 4 题解

CF660F Bear and Bowling 4 题解

对题目中的和式化简可以得到等价于:

\[\begin{aligned} &\sum_{i = l}^r (i - l + 1)a_i\\ =&\sum_{i = l}^r ia_i-(l - 1)a_i\\ =&is_r - is_{l - 1}-(l - 1)s_r+(l - 1)s_{l - 1} \end{aligned} \]

其中 \(is_i = \sum_{j = 1}^i ja_j, s_i = \sum_{j = 1}^i a_j\)

如果固定 \(l\),那么 \(-is_{l - 1}+(l -1)s_{l - 1}\) 都是定值,而 \(-(l - 1)s_r+is_r\) 可以被认为是 \(kx+b\) 的直线形式,使用你喜欢的凸包维护手段即可解决本题,李超树应该是比较高效的一种方式。

时间复杂度:\(O(n\log n)\)

// Problem: CF660F Bear and Bowling 4
// Author: Moyou
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#define int long long
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 2e5 + 10, INF = 1e18, V = 1e7;

int n, a[N], s[N], is[N], dat[N << 2];
struct Inori {
    int k, b;
} p[N];
int calc(int x, int v) {
    if(v == 0) return -INF;
    return x * p[v].k + p[v].b;
}
#define mid ((l + r) >> 1)
void update(int u, int l, int r, int v) {
    if(calc(mid, v) > calc(mid, dat[u])) swap(dat[u], v);
    if(l == r) return ;
    if(calc(l, v) > calc(l, dat[u])) update(u << 1, l, mid, v);
    if(calc(r, v) > calc(r, dat[u])) update(u << 1 | 1, mid + 1, r, v);
}
int query(int u, int l, int r, int x) {
    if(l == r) return calc(l, dat[u]);
    int t = calc(x, dat[u]);
    if(x <= mid) return max(query(u << 1, l, mid, x), t);
    return max(query(u << 1 | 1, mid + 1, r, x), t);
}

signed main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n;
    for(int i = 1; i <= n; i ++) cin >> a[i], s[i] = s[i - 1] + a[i], is[i] = is[i - 1] + i * a[i];
    int ans = 0;
    for(int i = n; i; i --) {
        p[i] = {-s[i], is[i]};
        update(1, 0, n, i);
        ans = max(ans, query(1, 0, n, i - 1) + (i - 1) * s[i - 1] - is[i - 1]);
    }
    cout << ans << '\n';

    return 0;
}

posted @ 2025-08-19 12:33  MoyouSayuki  阅读(7)  评论(0)    收藏  举报
:name :name