传送门

显然考虑 $dp$ ,发现从右往左和从左往右是一样的,所以只考虑一边就行

发现对于切的左右端点,选择的 $s0$ 一定要为左右端点的贝壳大小,不然这个端点不产生贡献还不如分开来单个贡献

所以设 $f[i]$ 表示当前把 $1$ 到 $i$ 的都切了,产生的最大贡献,设 $c[i]$ 表示位置 $i$ 及之前大小为 $s[i]$ 的柠檬个数,有转移:

$f[i]=f[j-1]+s[i](c[i]-c[j]+1)^2,j \in [1,i]$,并且要满足 $s[i]=s[j]$ ,发现是个斜率优化的式子,拆开来:

$f[i]=f[j-1]+s[i](c[i]^2-2c[i](c[j]-1)+(c[j]-1)^2)$,再拆,变成

$f[j-1]+s[i](c[j]-1)^2=2s[i]c[i](c[j]-1)+f[i]-s[i]c[i]^2$,因为转移都是在同一个大小之间转移,所以 $s[i]$ 可以看成常数

所以 $y=f[j-1]+s[i](c[j]-1)^2$,$k=2s[i]c[i]$,$x=c[j]-1$,$b=f[i]-s[i]c[i]^2$,对每种 $s$ 都维护一个凸包即可

显然对于同一个 $s$, $k,x$ 都单调递增,并且求 $max$ ,所以维护上凸包

插点时从右边插,更新 $f$ 时也切凸包右边,用 $vector$ 维护凸包即可

注意先加当前点再更新 $f$($j \in [1,i]$)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
typedef long double ldb;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=2e5+,M=2e4+;
int n,s[N],c[N],cnt[M];
ll f[N];
struct Vec{//向量
ldb x,y;
Vec (ll a=,ll b=) { x=a,y=b; }
inline ldb operator * (const Vec &tmp) const {
return x*tmp.y-y*tmp.x;
}
};
struct Poi{//凸包点
ll f; int cj,s;
Poi (ll a=,int b=,int c=) { f=a,cj=b,s=c; }
inline ll calc(int i) { return f+1ll*s*(c[i]-cj+)*(c[i]-cj+); }
inline ll X() { return 1ll*s*(cj-); }
inline ll Y() { return f+1ll*s*(cj-)*(cj-); }
};
inline Vec operator - (Poi &A,Poi &B) {
return Vec( A.X()-B.X() , A.Y()-B.Y() );
}
vector <Poi> st[M];//每种s维护凸包
int main()
{
n=read();
for(int i=;i<=n;i++)
s[i]=read(),c[i]=++cnt[s[i]];
for(int i=;i<=n;i++)
{
Poi t(f[i-],c[i],s[i]); int len=st[s[i]].size()-;
while( len> && (st[s[i]][len]-st[s[i]][len-])*(t-st[s[i]][len-])>= ) st[s[i]].pop_back(),len--;
st[s[i]].push_back(t); len++;//先插入
while( len> && st[s[i]][len].calc(i) <= st[s[i]][len-].calc(i) ) st[s[i]].pop_back(),len--;
f[i]=st[s[i]][len].calc(i);//再更新
}
printf("%lld\n",f[n]);
return ;
}

P5504 [JSOI2011]柠檬的更多相关文章

  1. luogu P5504 [JSOI2011]柠檬

    bgm(雾) luogu 首先是那个区间的价值比较奇怪,如果推导后可以发现只有左右端点元素都是同一种\(s_x\)的区间才有可能贡献答案,并且价值为\(s_x(cnt(x)_r-cnt(x)_{l-1 ...

  2. bzoj4709: [Jsoi2011]柠檬 斜率优化

    题目链接 bzoj4709: [Jsoi2011]柠檬 题解 斜率优化 设 \(f[i]\) 表示前 \(i\)个数分成若干段的最大总价值. 对于分成的每一段,左端点的数.右端点的数.选择的数一定是相 ...

  3. 4709: [Jsoi2011]柠檬

    4709: [Jsoi2011]柠檬 https://www.lydsy.com/JudgeOnline/problem.php?id=4709 分析: 决策单调性+栈+二分. 首先挖掘性质:每个段选 ...

  4. 【BZOJ】4709: [Jsoi2011]柠檬

    4709: [Jsoi2011]柠檬 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 779  Solved: 310[Submit][Status][ ...

  5. 【BZOJ4709】[Jsoi2011]柠檬 斜率优化+单调栈

    [BZOJ4709][Jsoi2011]柠檬 Description Flute 很喜欢柠檬.它准备了一串用树枝串起来的贝壳,打算用一种魔法把贝壳变成柠檬.贝壳一共有 N (1 ≤ N ≤ 100,0 ...

  6. 【LG5504】[JSOI2011]柠檬

    [LG5504][JSOI2011]柠檬 题面 洛谷 题解 考虑\(dp\),令\(f_i\)表示\(dp\)到第\(i\)位且在第\(i\)位分段的最大值. 我们令题面中的\(s_i\)为\(a_i ...

  7. 笔记-[JSOI2011]柠檬

    笔记-[JSOI2011]柠檬 [JSOI2011]柠檬 \(f_i\) 表示到第 \(i\) 只贝壳最多可以换得的柠檬数. 令 \(c_i=\sum_{h=1}^i[s_h=s_i]\). \[\b ...

  8. bzoj4709 [jsoi2011]柠檬

    Description Flute 很喜欢柠檬.它准备了一串用树枝串起来的贝壳,打算用一种魔法把贝壳变成柠檬.贝壳一共有 N (1 ≤ N  ≤ 100,000) 只,按顺序串在树枝上.为了方便,我们 ...

  9. 【bzoj4709】[Jsoi2011]柠檬 斜率优化

    题目描述 给你一个长度为 $n$ 的序列,将其分成若干段,每段选择一个数,获得 $这个数\times 它在这段出现次数的平方$ 的价值.求最大总价值. $n\le 10^5$ . 输入 第 1 行:一 ...

随机推荐

  1. 对15号夏壹队的TD信息通使用体验

    对夏壹队的APP的用户使用体验:首先下载的时候看到这个APP的大小是6M多点不算很大感觉还不错,但是占内存不大也说明了一个问题,它不会有很多的功能. 图标是一个蜜蜂,打开后会有一个登陆界面,一开始没有 ...

  2. day1 instance,round,divmod,imput, 字符串

      >>> a = '123' >>> isinstance(a, str) True >>> b = 1 >>> type(b ...

  3. js基础复习~Array对象

    Array对象 lenght 获取到数组的长度 concat() 方法用于合并两个或多个数组.此方法不会更改两大有数组,而是返回一个新的数组 let arr1 = ["a",&qu ...

  4. 多模字符串匹配算法-Aho–Corasick

    背景 在做实际工作中,最简单也最常用的一种自然语言处理方法就是关键词匹配,例如我们要对n条文本进行过滤,那本身是一个过滤词表的,通常进行过滤的代码如下 for (String document : d ...

  5. A1011

    找最大的,然后按规定计算后输出. 没啥可说的,除非犯了愚蠢的错误(比如把j写成i这种),按题目要求写就是了. #include<cstdio> int main(){ ]={'W','T' ...

  6. JavaScript自增和自减

    一.自增++ 通过自增运算符可以使变量在自身的基础上加一: 对于一个变量自增以后,原变量的值会立即自增一: 自增符号:++ 自增分为两种:1.后++(a++):2.前++(++a): 共同点:a++ ...

  7. HDU 6620 Just an Old Puzzle

    Time limit 2000 ms Memory limit 262144 kB OS Windows 解题过程 感觉搜索不可行,状态太多了,120步,判断状态是否重复时,即使用std::map也太 ...

  8. 封装通用的 ajax, 基于 jQuery。

    在前端异步获取数据时候每次都是使用 ajax:为了通用性更好,然而封装通用的 ajax 是一个一劳永逸的办法. 本次基于 jQuery 封装实现: 第一步: 引入 jQuery: <script ...

  9. 多项式总结(unfinished)

    试试以二级标题为主的格式. 多项式相关 注:本篇博客不包含\(FFT\)基础姿势.如果您想要阅读本篇博客,请确保自己对\(FFT,NTT\)有基本的认识并且能够独立写出代码. 多项式是什么? 左转数学 ...

  10. php简单随机实现发红包程序

    前言: 使用PHP发红包,当我们输入红包数量和总金额后,PHP会根据这两个值进行随机分配每个金额,保证每个人都能领取到一个红包,每个红包金额不等,就是要求红包金额要有差异,所有红包金额总额应该等于总金 ...