@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,表示树离地的 ...
随机推荐
- Ajax 用法简介
使用Ajax实现页面的局部刷新 一.不依赖jquery时是这样的用法: var xhr=new XMLHttpRequest(); xhr.onreadystatechange=function(ev ...
- Java方法传参的问题
1.基本数据类型(byte,short,int,long,float,double,boolean,char)的值传递,不改变其值 2.引用数据类型的值传递,改变其值 3.String类型虽然是引用数 ...
- mysql优化-数据库设计基本原则
mysql优化-数据库设计基本原则 一.数据库设计三范式 第一范式:字段具有原子性 原子性是指数据库的所有字段都不可被再次划分,如下表就不满足原子性,起点与终点 字段就可被拆分为起点与终点两个字段. ...
- day37 04-Hibernate二级缓存:list和iterate方法比较
get()和load()方法既可以向一级缓存区放数据,也可以向二级缓存区放数据.这是查询一个的情况.要是查询所有呢?注意, // 查询所有.Query接口的list()方法. // list()方法会 ...
- python实例 字典
#! /usr/bin/python x={'a':'aaa','b':'bbb','c':12} print (x['a']) print (x['b']) print (x['c']) for k ...
- python 处理缺失数据
- 洛谷 USACO P2207 Photo
P2207 Photo 题目描述 Framer Jhon 打算给他的N头奶牛照相,( 2 <= N <= 1 000 000 000) . 他们排成一条线,并且依次取1~N作为编号. 每一 ...
- 关于Ajax提交后无法刷新iframe页面的问题
原因及解决方法: 要把刷新代码写进ajax的代码块里面,而不是放在后面
- SSH 相关基础
检查是否安装: sudo apt-cache policy openssh-client sudo apt-cache policy openssh-server 也可直接用 sudo apt-ca ...
- python第一天 :计算机基础(一)
1.什么是编程语言 答:人类与计算机交流的介质 2.什么是编程 答:利用编程语言控制计算机解决问题 3.为什么要编程 答:可以控制计算机做事,提高生产生活效率 4.计算机的五大组成部分分别有什么作用? ...