Description

Flute 很喜欢柠檬。它准备了一串用树枝串起来的贝壳,打算用一种魔法把贝壳变成柠檬。贝壳一共有 N (1 ≤ N ≤ 100,000) 只,按顺序串在树枝上。为了方便,我们从左到右给贝壳编号 1..N。每只贝壳的大小不一定相同,贝壳 i 的大小为 si(1 ≤ si ≤10,000)。变柠檬的魔法要求,Flute 每次从树枝一端取下一小段连续的贝壳,并选择一种贝壳的大小 s0。如果 这一小段贝壳中 大小为 s0 的贝壳有 t 只,那么魔法可以把这一小段贝壳变成 s0t^2 只柠檬。Flute 可以取任意多次贝壳,直到树枝上的贝壳被全部取完。各个小段中,Flute 选择的贝壳大小 s0 可以不同。而最终 Flute 得到的柠檬数,就是所有小段柠檬数的总和。Flute 想知道,它最多能用这一串贝壳变出多少柠檬。请你帮忙解决这个问题。

Input

第 1 行:一个整数,表示 N。

第 2 .. N + 1 行:每行一个整数,第 i + 1 行表示 si。

Output

仅一个整数,表示 Flute 最多能得到的柠檬数。

Sample Input

5

2

2

5

2

3

Sample Output

21

//Flute 先从左端取下 4 只贝壳,它们的大小为 2, 2, 5, 2。选择 s0 = 2,那么这一段里有 3 只大小为 s0 的贝壳,通过魔法可以得到 2×3^2 = 18 只柠檬。再从右端取下最后一只贝壳,通过魔法可以得到 1×3^1 = 3 只柠檬。总共可以得到 18 + 3 = 21 只柠檬。没有比这更优的方案了。


思路

首先发现一个性质

对于选出来的每个区间,区间左端点种类和区间右端点相等,而且这一段区间选定的一定是端点的值,否则一定可以分离出没有用的区间另外计算贡献

然后我们发现对于任意的\(j_1<j_2<i_1<i_2\)

因为每一个种类的前缀和是单调递增的,且\(y=x^2\)是个下凸函数,所以如果在\(i_1\)处\(j_1\)比\(j_2\)更优,有\(i_2\)的时候\(j_1\)一定比\(j_2\)优

所以就可以对每个种类维护一个单调栈

这样就可以维护最优的决策点

但是为了保证决策和斜率都是单调的,在加入节点前我们可以判断,如果栈顶-1超过栈顶的最小前缀大小小于等于站顶超过当前节点的最小前缀大小,那么栈顶是无效的

然后在加入之后判断栈顶-1超过栈顶的前缀大小小于等于当前前缀最小,那么栈顶已经不优秀了,直接弹栈就可以了


//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define for_up(a, b, c) for (int a = b; a <= c; ++a)
#define for_down(a, b, c) for (int a = b; a >= c; --a)
#define for_vector(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
bool w = 1;x = 0;
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = 0, c = getchar();
while (isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if (!w) x = -x;
}
template <typename T>
void Write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
const int N = 1e5 + 10;
const int M = 1e4 + 10;
ll dp[N];
int n, a[N];
int pre[N], last[N], s[N];
vector<int> p[M];
ll cal(int lastpos, int vl) {
return dp[lastpos - 1] + 1ll * a[lastpos] * vl * vl;
}
int check(int x, int y) { // 算x点超过y点的最小前缀和
int l = 1, r = n, ans = n + 1;
while (l <= r) {
int mid = (l + r) >> 1;
if(cal(x, mid - s[x] + 1) >= cal(y, mid - s[y] + 1)) ans = mid , r = mid - 1;
else l = mid + 1;
}
return ans;
}
#define S(s) (signed)s.size()
#define R1(s) S(s) - 1
#define R2(s) S(s) - 2
#define now p[a[i]]
int main() {
Read(n);
for_up(i, 1, n) {
Read(a[i]);
last[i] = pre[a[i]];
s[i] = s[last[i]] + 1;
pre[a[i]] = i;
}
for_up(i, 1, n) {
while (S(now) > 1 && check(now[R2(now)], now[R1(now)]) <= check(now[R1(now)], i)) now.pop_back();
now.push_back(i);
while (S(now) > 1 && check(now[R2(now)], now[R1(now)]) <= s[i]) now.pop_back();
dp[i] = cal(now[R1(now)], s[i] - s[now[R1(now)]] + 1ll);
}
Write(dp[n]);
return 0;
}

最新文章

  1. spring boot(四):thymeleaf使用详解
  2. selenium-webdriver(python) (十六) --unittest 框架
  3. Vector3 *2 ,ToString()自动四舍五入
  4. iOS开发——常见错误——使用MJRefresh返回上一个界面蹦掉的情况
  5. c#面向对象基础 封装、继承
  6. python-基础案例
  7. (转)springAOP解析-1
  8. asp.net跨页面传值
  9. 【ASP.NET】DataContract序列化,反序列化对象中包含用接口声明的属性时的处理方法
  10. js split str.split(&amp;quot; &amp;quot;); split使用方法 在某处截字符串
  11. .NET Entity Framework入门简介及简单操作
  12. c语言,链表
  13. Log4j扩展使用--输出地Appender
  14. ide phpStorm更换主题
  15. 说一说js中的闭包
  16. linux下export命令添加、删除环境变量(转载)
  17. ArcPy批量计算Mean Center的两个实例
  18. UML和模式应用5:细化阶段(10)---UML交互图
  19. Solr中的日期/时间表示
  20. vue如何加入百度ssp广告位代码

热门文章

  1. 一些常用的CDN列表
  2. 公众号菜单中的click
  3. jquery插件之jquery-ui
  4. ajax实现用户注册
  5. OSI7层网络模型协议精析
  6. python脚本11_求10万以内所有素数
  7. SQL 2008R2还原对于服务器失败 备份集中的数据库与现有数据库 3154错误
  8. 51nod-1574-排列转换
  9. Opencv+pycharm+anaconda配置
  10. AS3帮助手册