La secuencia de los 72 C brz del juego de práctica de Niu Ke (pensamiento + casco convexo)

Enlace: https://ac.nowcoder.com/acm/contest/8282/C
Fuente: Niuke
 

Límite de tiempo: C / C ++ 1 segundo, otros idiomas 2 segundos
Límite de espacio: C / C ++ 524288K, otros idiomas 1048576K
64bit IO Formato:% lld

Descripción del Título

El lzy \ text {lzy} lzy gigante no tiene nada que hacer, y le dio a konjac brz \ text {brz} brz una secuencia a de longitud n, y le permite a konjac operar esta secuencia, tal como la define el lzy \ text {lzy} gigante lzy, Una operación es seleccionar un i∈ (1, n) i \ in (1, n) i∈ (1, n), y luego convertir el i-ésimo número en la secuencia en el promedio de los dos números adyacentes , Es decir, ai = ai − 1 + ai + 12a_i = \ dfrac {a_ {i-1} + a_ {i + 1}} 2ai = 2ai − 1 + ai + 1.

Konjac brz \ text {brz} brz quería minimizar la suma de la secuencia, pero no era muy bueno manipulando, y no se atrevía a chillar frente a los gigantes, así que tuvo que preguntarte en secreto: ¿dónde estás? puede realizar tiempos ilimitados en cualquier posición En el caso de operación, ¿cuál es la suma mínima de secuencias que se puede obtener?

Ingrese descripción:

 

Un número entero n en la primera línea indica la longitud de la secuencia.

Los n enteros en la segunda línea representan esta secuencia.

1≤n≤106,1≤ai≤1091 \ leq n \ leq 10 ^ 6,1 \ leq a_i \ leq 10 ^ 91≤n≤106,1≤ai ≤109

Descripción de salida:

输出一个实数,表示能得到的序列最小总和,保留到小数点后十位。

Ejemplo 1

ingresar

3
1 2 2

Producción

4.5000000000

Descripción

操作一次序列的第二个数,使其变成1+2​=1.5,序列总和就是1+1.5+2=4.5,可以证明序列总和无法变得更小。

Ideas:

Se puede encontrar que cuando un intervalo se convierte en una secuencia aritmética, ya no puede ser más pequeño El problema se transforma aún más en seleccionar algunos intervalos de la secuencia original para convertirlo en una secuencia aritmética.

No es que la suma de cualquier intervalo se convierta en la más pequeña cuando se convierte en una secuencia aritmética. La suma del intervalo original será la más pequeña sólo cuando los números, excepto el principio y el final, sean mayores que el número correspondiente en la secuencia aritmética.

Los números en la secuencia se  ai] abstraen como puntos en el sistema de coordenadas,  (yo, un [i])y el problema se transforma en encontrar el casco convexo inferior. (Dado que la secuencia original ya está ordenada por la coordenada x, esta pregunta no necesita ser ordenada de antemano por ángulo polar

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps = 1e-11;
const int N = 1e6 + 10;

int sgn(double x) {
    if(fabs(x) < eps) return 0;
    if(x < 0) return -1;
    else return 1;
}

struct Point
{
	double x, y;
	Point(){}
	//定义运算
	Point(double _x, double _y) {
        x = _x;
        y = _y;
    }
	bool operator == (Point b) const {
        return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
	}
	bool operator < (Point b) const {
        return sgn(x - b.x) == 0 ? sgn(y - b.y) < 0 : x < b.x;
	}
	Point operator - (const Point &b) const {
        return Point(x - b.x, y - b.y);
	}
    double operator ^ (const Point &b) const {
        return x * b.y - y * b.x;
	}
} p[N], st[N];

int main() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        scanf("%lf", &p[i].y);
        p[i].x = 1.0 * i;
    }
    int top = 0;
    for(int i = 1; i <= n; ++i) {
        while(top > 1 && ((p[i] - st[top - 1]) ^ (st[top] - st[top - 1])) > 0.0) --top;
        st[++top] = p[i];
    }
    double ans = 0.0;
    for(int i = 2; i <= top; ++i)
        ans += 1.0 * (st[i].y + st[i - 1].y) * (st[i].x - st[i - 1].x + 1) / 2.0 - st[i].y;
    ans += st[top].y;
    printf("%.10f\n", ans);
    return 0;
}

 

Supongo que te gusta

Origin blog.csdn.net/weixin_43871207/article/details/109544233
Recomendado
Clasificación