[题解] [JSOI2011] 柠檬

题面

题解

斜率优化入门练习题, 不想写题解了
左转大仙博客, 然后你就能切了这道题哦

Code

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
const int N = 100005;
const int M = 10005;
#define int long long
#define t1 vec[c[i]][vec[c[i]].size() - 1]
#define t2 vec[c[i]][vec[c[i]].size() - 2]
using namespace std;

int n, c[N], last[M], sum[N], f[N];
vector<int> vec[M]; 

template < typename T >
inline T read()
{
    T x = 0, w = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * w; 
}

double calc(int x, int y)
{
    return 1.0 * (f[x - 1] - f[y - 1] + c[x] * (sum[x] * (sum[x] - 2) - sum[y] * (sum[y] - 2))) / (2.0 * c[x] * (sum[x] - sum[y])); 
}

signed main()
{
    n = read <int> ();
    for(int i = 1; i <= n; i++)
	c[i] = read <int> (), sum[i] = sum[last[c[i]]] + 1, last[c[i]] = i; 
    for(int i = 1; i <= n; i++)
    {
	while(vec[c[i]].size() >= 2 && calc(i, t1) >= calc(t1, t2))
	    vec[c[i]].pop_back();
	vec[c[i]].push_back(i);
	while(vec[c[i]].size() >= 2 && calc(t1, t2) < sum[i])
	    vec[c[i]].pop_back(); 
	f[i] = f[t1 - 1] + c[i] * (sum[i] - sum[t1] + 1) * (sum[i] - sum[t1] + 1); 
    }
    printf("%lld\n", f[n]); 
    return 0; 
}
posted @ 2020-02-04 11:11  ztlztl  阅读(127)  评论(0)    收藏  举报