AtCoder Beginner Contest 240 F - Sum Sum Max

原题链接F - Sum Sum Max

首先令zi=k=1iykz0=0zi就是第i段相同的个数的前缀和.

对于第i段和i1段,我们有zi1kzi,这一段的值就全是xi,相当于Ck=xi.

对于某一段1nzizi1,有nxi

Bzi1+n=Bzi1+nxi

Azi1+n=Azi1+k=1nBzi1+k=Azi1+k=1n(Bzi1+Kxi)=Azi1+Bzi1n+xi×n(n+1)2

Azi1+n=an2+bn+c看成一个二次函数f(n),所以我们的任务就是对于1nzizi1,求f的最值.

如果a>0,那么最大值在两端点f(1)f(zizi1)处取得。
如果a<0,那么就是单峰函数,我们可以使用三分,令ml=(l+r)/2,mr=ml+1,结束条件rl>2,那么最终结束rl==2,所以我们的最值就是f(l+r)或者f(r1)

#include <bits/stdc++.h>

using namespace std;

using ll = long long;

template<typename F> ll ternary_search(ll l, ll r, const F& f) {
    while (r - l > 2) {
        const ll ml = (l + r) / 2;
        const ll mr = ml + 1;
        if (f(ml) < f(mr)) {
            l = ml;
        } else {
            r = mr;
        }
    }
    
    return f(l + 1);
}

void solve() {
    int n, m;
    cin >> n >> m;
    ll res = numeric_limits<ll>::min();
    ll a = 0, b = 0;
    for (int i = 1; i <= n; i++) {
        ll x, y; cin >> x >> y;
        const auto f = [&](const ll k) {
            return a + b * k + k * (k + 1) / 2 * x;
        };

        if (x > 0) {
            res = max({res, f(1), f(y)});
        } else {
            res = max(res, ternary_search(0, y + 1, f));
        }
        a = f(y);
        b += x * y;
    }

    cout << res << "\n";
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0);

    int test;
    cin >> test;
    for (int i = 0; i < test; ++i) solve();

    return 0;
}
posted @   Xxaj5  阅读(131)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示