题目描述

给你一个长度为 $n$ 的序列,将其分成若干段,每段选择一个数,获得 $这个数\times 它在这段出现次数的平方$ 的价值。求最大总价值。

$n\le 10^5$ 。

输入

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

输出

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

样例输入

5
2
2
5
2
3

样例输出

21


题解

斜率优化

设 $f[i]$ 表示前 $i$ 个数分成若干段的最大总价值。

显然对于分成的每一段,左端点的数、右端点的数、选择的数一定是相同的。因为如果不相同则可以从这个段里删去这个数,答案会更优。

于是就有转移:$f_i=f_{j-1}+a·(c_i-c_j+1)^2\ ,\ j\le i\ ,\ a_j=a_i$ ,其中 $a$ 表示原序列,$c$ 表示这个位置时这个数第几次出现(即出现次数的前缀和)。

显然这个式子可以斜率优化,整理得:$f_{j-1}+a·(c_j-1)^2=ac_i·2(c_j-1)+f_i-ac_i^2$ ,其中 $y$ 是 $f_{j-1}+a·(c_j-1)^2$ ,$k$ 是 $ac_i$  ,$x$ 是 $2(c_j-1)$ ,$b$ 是 $f_i-ac_i^2$ 。

这里 $k$ 单调递增,$x$ 单调递增,然而要求的是 $b$ 的最大值,因此只能使用单调栈维护上凸壳。对每种数开一个vector即可。询问时在vector上二分。

时间复杂度 $O(n\log n)$

#include <cstdio>
#include <vector>
#define N 100010
#define y(i) (f[i - 1] + a[i] * squ(c[i] - 1))
#define x(i) 2 * (c[i] - 1)
using namespace std;
typedef long long ll;
vector<int> v[10010];
ll cnt[10010] , c[N] , f[N];
int a[N];
inline ll squ(ll x)
{
return x * x;
}
int main()
{
int n , i , l , r , mid , ret , t;
scanf("%d" , &n);
for(i = 1 ; i <= n ; i ++ )
{
scanf("%d" , &a[i]) , c[i] = ++cnt[a[i]];
while((t = v[a[i]].size() - 1) > 0 && (x(i) - x(v[a[i]][t])) * (y(v[a[i]][t - 1]) - y(v[a[i]][t])) - (y(i) - y(v[a[i]][t])) * (x(v[a[i]][t - 1]) - x(v[a[i]][t])) > 0) v[a[i]].pop_back();
v[a[i]].push_back(i);
l = 1 , r = v[a[i]].size() - 1 , ret = 0;
while(l <= r)
{
mid = (l + r) >> 1;
if(f[v[a[i]][mid] - 1] + a[i] * squ(c[i] - c[v[a[i]][mid]] + 1) > f[v[a[i]][mid - 1] - 1] + a[i] * squ(c[i] - c[v[a[i]][mid - 1]] + 1)) ret = mid , l = mid + 1;
else r = mid - 1;
}
f[i] = f[v[a[i]][ret] - 1] + a[i] * squ(c[i] - c[v[a[i]][ret]] + 1);
}
printf("%lld\n" , f[n]);
return 0;
}

最新文章

  1. 5.2 Array类型介绍
  2. mongodb_查询操作使用_条件查询、where子句等(转)
  3. UVa 106 - Fermat vs Pythagoras(数论题目)
  4. Hibernate validation 注解 springmvc 验证 分组
  5. 无线安全渗透测试套件WiFi-Pumpkin新版本发布
  6. asp.net MVC 自定义@helper 和自定义函数@functions小结
  7. graphicsMagick 文档
  8. Apache Commons Pool2 源码分析 | Apache Commons Pool2 Source Code Analysis
  9. BNU Online Judge-29140
  10. Java:extends和implements的区别+用法
  11. 装饰模式(Decorator)
  12. SQL Server之LEFT JOIN、RIGHT LOIN、INNER JOIN的区别
  13. VirtualBox不能为虚拟电脑打开一个新任务——The VirtualBox kernel modules do not match this version of VirtualBox
  14. WCF优雅使用 KnownType标记的方法
  15. iOS中的copy
  16. NSIS 资料
  17. 基于Keras的imdb数据集电影评论情感二分类
  18. CentOS 多版本python安装pip
  19. 位运算(Bit Manipulation)在算法中的应用
  20. TCP中三次握手建立和四次握手释放以及相关问题

热门文章

  1. 安装centos minimal 版本后安装mysql详细过程(linux)
  2. IDEA 创建Spring Boot 项目
  3. javascript 强制转换规则 boolean 布尔值类型
  4. Python中元祖,列表,字典的区别
  5. Zabbix部署-LNMP环境
  6. [转载]文件系统缓存dirty_ratio与dirty_background_ra
  7. spring第一章
  8. 【C#】人脸识别 视频数据转图片数据
  9. hadoop之mapper类妙用
  10. 重构:越来越长的 switch ... case 和 if ... else if ... else