@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,表示树离地的 ...
随机推荐
- torch.backends.cudnn.benchmark = true 使用情形
设置这个 flag 可以让内置的 cuDNN 的 auto-tuner 自动寻找最适合当前配置的高效算法,来达到优化运行效率的问题. 应该遵循以下准则: 如果网络的输入数据维度或类型上变化不大,设置 ...
- 直白介绍卷积神经网络(CNN)【转】
英文地址:https://ujjwalkarn.me/2016/08/11/intuitive-explanation-convnets/ 中文译文:http://mp.weixin.qq.com/s ...
- Win7系统中wmiprvse.exe占用CPU高如何解决
该进程的详细路径是在:C:\WINDOWS\System32\Wbem 我们可以在任务管理器中“wmiprvse.exe”进程上单击右键,选择“打开文件位置”即可看到,如果该文件不在该文件夹中,那么 ...
- Python 匹配IP地址的正则表达式
- BZOJ1076奖励关题解
链接 很容易想到状压,f[i][s]表示前i个选择的箱子集合为s的最大期望 果断wa了,因为有一些不合法的状态,譬如f[1][1111001]这样的状态 这样的状态不好排除,所以改用倒推 用f[i][ ...
- 如何用KNIME进行情感分析
Customer Intelligence Social Media Finance Credit Scoring Manufacturing Pharma / Health Care Retail ...
- 手机端 echarts使用 svg渲染器
// 使用 Canvas 渲染器(默认) var chart = echarts.init(containerDom, null, {renderer: 'canvas'}); // 等价于: var ...
- Array操作的方法
//concat连接数组连接一个或多个数组 //var a = [1,2,3]; //var c=[4,5] //var b = a.concat(c); //console.log(b); //jo ...
- 洛谷 P3258 [JLOI2014]松鼠的新家 树链剖分+差分前缀和优化
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 说明 思路 AC代码 优化 优化后AC代码 总结 题面 题目链接 P3258 [JLOI2 ...
- EasyUI 网格 一主多从 从表使用自定义树状展开
<table id="Table1" class="easyui-datagrid" title="标题" style="w ...