@bzoj - 4709@ 柠檬
@desription@
一共有 N 只贝壳,编号为 1...N,贝壳 i 的大小为 si。
Flute 每次可以取一段连续的贝壳,并选择 s0。如果这些贝壳中大小为 s0 的贝壳有 t 只,就通过魔法把这些贝壳变成 s0*t^2 只柠檬。
经过任意次魔法取完贝壳,最终 Flute 得到的柠檬数是所有小段柠檬数的总和。问最多能变出多少柠檬。
input
第 1 行:一个整数,表示 N(1 ≤ N ≤ 100,000)。
第 2 .. N + 1 行:每行一个整数,第 i + 1 行表示 si(1 ≤ si ≤10,000)。
output
仅一个整数,表示 Flute 最多能得到的柠檬数。
sample input
5
2
2
5
2
3
sample output
21
sample explain
Flute 先从取下 4 只贝壳,它们的大小为 2, 2, 5, 2。选择 s0 = 2,那么这一段
里有 3 只大小为 s0 的贝壳,通过魔法可以得到 2×3^2 = 18 只柠檬。再从右端取下最后一只贝壳,通过魔法可以得到 1×3^1 = 3 只柠檬。总共可以得到 18 + 3 = 21 只柠檬。没有比这更优的方案了。
@solution@
有这样一个性质:假如你对于区间 [l, r] 选的贝壳大小为 s0,则贝壳 l 与 r 的大小为 s0。
如果区间的左右端点的大小不为 s0,则你可以往内缩端点直到等于为止,此时这个区间的答案不会变化。
这样我们就可以来设计 dp 了。
定义状态 \(dp[i]\) 表示取完 1~i 这些贝壳所能求得的最大柠檬数,再定义 \(f[i]\) 表示 i 前面的,与 i 大小相同的贝壳数量(类前缀和)。
则有状态转移:
\]
长得非常 “斜率优化”,我们拆开括号再仔细来看一看:
\]
注意 s[i] = s[j]。所以式子还可以变为:
\]
然后就可以斜率优化了。其中横坐标 \(x[j] = 2*f[j]\),纵坐标 \(y[j] = dp[j-1]+s[j]*f[j]^2\),斜率 \(k[i]=s[i]*f[i]\)。
我们对于每一个 \(s[i]\) 分别进行斜率优化,斜率 \(s[i]*f[i]\) 是单增的,横坐标 \(2*f[j]\) 也是单增,求最大值即上凸包,对于每一个 \(s[i]\) 都开一个单调栈就 OK 了。
讲一点代码细节:同时维护多个单调栈可以不用 vector 或者 deque 等动态的存储,因为我们已知了所有不同类型的 si 对应的元素个数,所以它的单调栈长度必然不会超过这个值。
我们开一个总的长度为 N 的空间,然后按照元素个数分配栈顶的指针即可。
@accepted code@
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 100000;
const int MAXS = 10000;
ll dp[MAXN + 5], sum[MAXN + 5];
int nxt[MAXN + 5], adj[MAXN + 5], s[MAXN + 5];
ll c(int i) {return (sum[i] + 1)*(sum[i] + 1)*s[i];}
ll k(int i) {return 2LL*s[i]*(sum[i] + 1);}
ll x(int j) {return sum[j];}
ll y(int j) {return dp[j-1] + sum[j]*sum[j]*s[j];}
double slope(int p, int q) {return 1.0*(y(p) - y(q))/(x(p) - x(q));}
int stk[MAXN + 5], tp[MAXS + 5], cnt[MAXS + 5];
int main() {
int N; scanf("%d", &N);
for(int i=1;i<=N;i++) {
scanf("%d", &s[i]);
sum[i] = sum[adj[s[i]]] + 1;
nxt[i] = adj[s[i]];
adj[s[i]] = i;
cnt[s[i]]++;
}
for(int i=1;i<=MAXS;i++)
cnt[i] += cnt[i-1];
for(int i=1;i<=MAXS;i++)
tp[i] = cnt[i-1];
for(int i=1;i<=N;i++) {
while( tp[s[i]] > cnt[s[i]-1] + 1 && slope(stk[tp[s[i]]], i) >= slope(stk[tp[s[i]] - 1], stk[tp[s[i]]]) )
tp[s[i]]--;
stk[++tp[s[i]]] = i;
while( tp[s[i]] > cnt[s[i]-1] + 1 && slope(stk[tp[s[i]] - 1], stk[tp[s[i]]]) <= k(i) )
tp[s[i]]--;
dp[i] = c(i) + y(stk[tp[s[i]]]) - k(i)*x(stk[tp[s[i]]]);
}
printf("%lld\n", dp[N]);
}
@details@
一开始我想的是对于每一个 si 都从头到尾作一遍 dp,这样就只需要一个单调栈了。
后来发现,不同的 si 之间也会相互影响,所以我只能从前往后老老实实维护多个单调栈了……
@bzoj - 4709@ 柠檬的更多相关文章
- bzoj 4709 [Jsoi2011]柠檬——单调栈二分处理决策单调性
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4709 题解:https://blog.csdn.net/neither_nor/articl ...
- bzoj 4709: [Jsoi2011]柠檬
Description Flute 很喜欢柠檬.它准备了一串用树枝串起来的贝壳,打算用一种魔法把贝壳变成柠檬.贝壳一共有 N (1 ≤ N ≤ 100,000) 只,按顺序串在树枝上.为了方便,我们从 ...
- 【BZOJ 4709】柠檬 斜率优化dp+单调栈
题意 给$n$个贝壳,可以将贝壳分成若干段,每段选取一个贝壳$s_i$,这一段$s_i$的数目为$num$,可以得到$num^2\times s_i$个柠檬,求最多能得到几个柠檬 可以发现只有在一段中 ...
- bzoj 4709 [ Jsoi2011 ] 柠檬 —— 斜率优化DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4709 课上讲的题,还是参考了博客...:https://www.cnblogs.com/GX ...
- 单调性优化DP
单调性优化DP Tags:动态规划 作业部落链接 一.概述 裸的DP过不了,怎么办? 通常会想到单调性优化 单调队列优化 斜率优化 决策单调性 二.题目 [x] 洛谷 P2120 [ZJOI2007] ...
- bzoj 2216 [Poi2011]Lightning Conductor——单调队列+二分处理决策单调性
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2216 那个关于位置的代价是带根号的,所以随着距离的增加而增长变慢:所以靠后的位置一旦比靠前的 ...
- 【BZOJ】4709: [Jsoi2011]柠檬
4709: [Jsoi2011]柠檬 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 779 Solved: 310[Submit][Status][ ...
- 4709: [Jsoi2011]柠檬
4709: [Jsoi2011]柠檬 https://www.lydsy.com/JudgeOnline/problem.php?id=4709 分析: 决策单调性+栈+二分. 首先挖掘性质:每个段选 ...
- 1502: [NOI2005]月下柠檬树 - BZOJ
Description Input 文件的第1行包含一个整数n和一个实数alpha,表示柠檬树的层数和月亮的光线与地面夹角(单位为弧度).第2行包含n+1个实数h0,h1,h2,…,hn,表示树离地的 ...
随机推荐
- Listview的条目item内的点击响应事件
还是这张图 这里的历史列表就是一个ListView,抛开该界面中ScrollView或者RecycleView与该ListView会有冲突,所谓的冲突,说白了就是父控件与子控件两者间的关系冲突,该冲突 ...
- GDOI2017第二轮模拟day1 总结
平民比赛 这场比赛的暴力分非常友好. 但是我并没有拿到全部的暴力分. 1(暴力分\(60/100\)) 暂时我可以拿的暴力分为\(30/100\),直接mst模拟即可. 然而当时打了个辣鸡莫队,结果爆 ...
- C++学习笔记----4.4 继承情况下的类作用域嵌套
引言: 在继承情况下,派生类的作用域嵌套在基类作用域中:如果不能在派生类作用域中确定名字,就在外围基类作用域中查找该名字的定义. 正是这种类作用域的层次嵌套使我们能够直接访问基类的成员,就好像这些成员 ...
- vs code 配置c/c++环境
1. 编译 通过 code-runner插件 运行编译 安装code-runner后在settings.json中找到code-runner.executorMap,可以看到其中的cpp 文件运行方式 ...
- UI标签库专题五:JEECG智能开发平台 Tabs(选项卡父标签)
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/zhangdaiscott/article/details/28956223 tools string ...
- Vue 实现展开折叠效果
Vue 实现展开折叠效果 效果参见:https://segmentfault.com/q/1010000011359250/a-1020000011360185 上述链接中,大佬给除了解决方法,再次进 ...
- vue2.0 兼容ie9及其以上
vue官方的意思是vue项目可以在ie8以上的ie版本中运行 但其实使用vue-cli构建的项目也还是不能在ie8[ie9,ie10,ie11]以上的版本中运行 下面就来讲vue如何在ie8以上ie版 ...
- Centos6.x终端中文乱码
locale LANG LC_*的默认值,是最低级别的设置,如果LC_*没有设置,则使用该值.类似于 LC_ALL. LC_ALL 它是一个宏,如果该值设置了,则该值会覆盖所有LC_*的设置值.注意 ...
- pytest fixture 利用 params参数实现用例集合
@pytest.fixture有一个params参数,接受一个列表,列表中每个数据都可以作为用例的输入.也就说有多少数据,就会形成多少用例.如下面例子,就形成3条用例 test_parametrizi ...
- 遗传算法MATLAB实现(3):多元函数优化举例
多峰的Shubert为: 求f(x,y)在[-10,10]x[-10,10]上的最大值. MATLAB代码: fun_mutv函数为: function my=fun_mutv(x,y) t1=zer ...