Участник:ZhenyaStrelkova/APIO10A

Материал из DISCOPAL
Перейти к: навигация, поиск

https://www.spoj.com/problems/APIO10A/

#include <iostream>
#include <cmath>
#include <limits>
 
using namespace std;
const int max_n = 2000007;
const double max_double = numeric_limits<double>::max();
 
long sqr(long x) { return x * x; }
 
long a, b, c, x[max_n], pref[max_n], z[max_n];
int n, top, st[max_n];
double alpha[max_n], beta[max_n];
 
double intersect(int i, int j) {
    double mi = -2 * a * pref[i];
    double pi = z[i] + a * sqr(pref[i]) - b * pref[i];
    double mj = -2 * a * pref[j];
    double pj = z[j] + a * sqr(pref[j]) - b * pref[j];
    return (pj - pi + 0.00) / (mi - mj);
}
 
long f(int k) {
    return a * sqr(pref[k]) + b * pref[k] + c;
}
 
int cond(int i, int j, int k) {
    long mi = -2 * a * pref[i];
    long mj = -2 * a * pref[j];
    long mk = -2 * a * pref[k];
    long pi = z[i] + a * sqr(pref[i]) - b * pref[i];
    long pj = z[j] + a * sqr(pref[j]) - b * pref[j];
    long pk = z[k] + a * sqr(pref[k]) - b * pref[k];
    return log(mk - mj) + log(pi - pk) <= log(mk - mi) + log(pj - pk);
}
 
int main() {
    int low, high, mid, t;
    double u, v;
    int T;
    cin >> T;
    for (int ts = 0; ts < T; ts++) {
        cin >> n >> a >> b >> c;
        for (int i = 1; i <= n; ++i) {
            cin >> x[i];
            pref[i] = pref[i - 1] + x[i];
        }
        z[1] = f(1);
        top = 0;
        st[++top] = 1;
        alpha[top] = -max_double;
        beta[top] = max_double;
        for (int k = 1; k < n; ++k) {
            if (pref[k + 1] >= alpha[top]) {
                t = st[top];
            } else {
                low = 1;
                high = top;
                while (low + 1 < high) {
                    pref[k + 1] < alpha[mid = (low + high) / 2] ? (high = mid) : (low = mid);
                }
                t = st[low];
            }
            long x1 = z[k] + a * sqr(x[k + 1]) + b * x[k + 1] + c;
            long x2 = f(k + 1) - 2 * a * pref[t] * pref[k + 1] + z[t] + a * sqr(pref[t]) - b * pref[t];
            long x3 = a * sqr(pref[k + 1]) + b * pref[k + 1] + c;
            z[k + 1] = max(x1, x2);
            z[k + 1] = max(z[k + 1], x3);
            for (; top >= 2;)
                if (!cond(st[top - 1], st[top], k + 1))
                    --top;
                else
                    break;
            beta[top] = intersect(st[top], k + 1);
            st[++top] = k + 1;
            alpha[top] = beta[top - 1];
            beta[top] = max_double;
        }
        cout << z[n] << "\n";
    }
    return 0;
}