【BZOJ4709】【Jsoi2011】柠檬
Description
  
  传送门
  
  题意简述:将序列划分成任意多段,从每一段选出一个数\(x\),获得\(在这一段出现的次数x*(x在这一段出现的次数)\)的贡献。求总贡献最大值。
  
  
  
  
  
Solution
  
  首先,要发现一个很重要的性质:如果某一段选了\(x\),那么这一段一定是以\(x\)开头、以\(x\)结尾的一段。否则,可以将此段缩减至以\(x\)开头、以\(x\)结尾的更小的一段,虽然贡献没有变,但留给其他段的机会更多。
  
  设\(f_i\)表示\(1...i\)的贡献最大值。记\(a_i\)表示\(i\)的数值,\(b_i\)表示\(a_i\)在相同的值中是第几个出现的。显然如果要从别的\(f_j\)转移到\(f_i\),必须满足\(a_{j+1}==a_i\)。我们有转移方程:
\]
设\(j\)为最优转移点:
f_i&=f_{j-1}+a_i(b_i-(b_j-1))^2\\
f_i&=f_{j-1}+a_i(b_i^2-2b_i(b_j-1)+(b_j-1)^2)\\
f_i&=f_{j-1}+a_ib_i^2-2a_ib_i(b_j-1)+a_i(b_j-1)^2\\
f_{j-1}+a_i(b_j-1)^2&=2a_ib_i(b_j-1)+f_i-a_ib_i^2
\end{aligned}
\]
  这其实是一个直线的式子:\(k=2a_ib_i\),\(x=(b_j-1)\),\(b=(f_i-a_ib_i^2)\),\(y=f_{j-1}+a_i(b_j-1)^2\).
  
  其中\(a_i\)看似和\(i\)有关,无法继续推理。但由于转移的\(j\)满足\(a_j=a_i\),所以每一个位置的数在参与上述DP时,相关联的\(a\)其实就是每一个元素自己的数值,是一个定值。
  
  把每一个元素看成二维平面的一个点\((x,y)\)。由于最优转移相当于最大化截距,那么最优转移点\(j\)可以看做在斜率为\(k\)的时候上凸包碰到的第一个点。
  
  那么我们扫描序列时,维护每一个数值对应的上凸包,每次查询时在上面二分即可。
  
  时间复杂度\(\mathcal O(n \lg n)\)。
  
  当然,也可以用斜率优化直接做。
  
  
  
Code
#include <cstdio>
#include <vector>
#define k(i) (2LL*a[i]*b[i])
#define x(i) (b[i]-1LL)
#define y(i) (f[i-1]+1LL*a[i]*(b[i]-1)*(b[i]-1))
#define b(i) (f[i]-1LL*a[i]*b[i]*b[i])
#define pb push_back
#define db pop_back
using namespace std;
typedef long long ll;
const int N=100005,S=10005;
const double EPS=1e-6;
int n,a[N],ecnt[S],b[N];
ll f[N];
vector<int> s[S];
int slen[S];
double slope(int u,int v){return 1.0*(y(v)-y(u))/(x(v)-x(u));}
int query(int col,int k){
	k=2*col*k;
	int l=0,r=slen[col]-2,mid;
	while(l<=r){
		mid=(l+r)>>1;
		if(slope(s[col][mid],s[col][mid+1])-EPS<=k) r=mid-1;
		else l=mid+1;
	}
	return s[col][l];
}
void insert(int col,int i){
	int sz=slen[col];
	while(sz>1&&slope(s[col][sz-2],s[col][sz-1])<slope(s[col][sz-1],i))
		sz--,slen[col]--,s[col].db();
	s[col].pb(i);
	slen[col]++;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",a+i);
		b[i]=++ecnt[a[i]];
	}
	for(int i=1;i<=n;i++){
		insert(a[i],i);
		int j=query(a[i],b[i]);
		f[i]=(j?f[j-1]:f[i-1])+1LL*a[i]*(b[i]-b[j]+1)*(b[i]-b[j]+1);
	}
	printf("%lld\n",f[n]);
	return 0;
}
【BZOJ4709】【Jsoi2011】柠檬的更多相关文章
- bzoj4709: [Jsoi2011]柠檬 斜率优化
		题目链接 bzoj4709: [Jsoi2011]柠檬 题解 斜率优化 设 \(f[i]\) 表示前 \(i\)个数分成若干段的最大总价值. 对于分成的每一段,左端点的数.右端点的数.选择的数一定是相 ... 
- bzoj4709 [jsoi2011]柠檬
		Description Flute 很喜欢柠檬.它准备了一串用树枝串起来的贝壳,打算用一种魔法把贝壳变成柠檬.贝壳一共有 N (1 ≤ N ≤ 100,000) 只,按顺序串在树枝上.为了方便,我们 ... 
- BZOJ4709 Jsoi2011 柠檬【决策单调性+单调栈】
		Description Flute 很喜欢柠檬.它准备了一串用树枝串起来的贝壳,打算用一种魔法把贝壳变成柠檬.贝壳一共有 N (1 ≤ N ≤ 100,000) 只,按顺序串在树枝上.为了方便,我们从 ... 
- BZOJ4709 JSOI2011柠檬(动态规划)
		首先要冷静下来发现这仅仅是在划分区间.显然若有相邻的数字相同应当划分在同一区间.还有一个显然的性质是区间的两端点应该相同且选择的就是端点的数.瞬间暴力dp就变成常数极小100002了.可以继续斜率优化 ... 
- [BZOJ4709][JSOI2011]柠檬(斜率优化DP)
		显然选出的每一段首尾都是相同的,于是直接斜率优化,给每个颜色的数开一个单调栈即可. #include<cstdio> #include<vector> #include< ... 
- [BZOJ4709][JSOI2011]柠檬 决策单调性优化dp
		题解: 解法1: 单调栈优化 首先发现一个性质就是 如果当前从i转移比从j转移更加优秀 那么之后就不会从j转移 所以我们考虑利用这个性质 我们要维护一个队列保证前一个超过后一个的时间单调不减 怎么来维 ... 
- BZOJ4709: [Jsoi2011]柠檬(决策单调性)
		题意 题目链接 Sol 结论:每次选择的区间一定满足首位元素相同.. 仔细想想其实挺显然的,如果不相同可以删掉多着的元素,对答案的贡献是相同的 那么设\(f[i]\)表示到第\(i\)个位置的最大价值 ... 
- 【BZOJ4709】[Jsoi2011]柠檬 斜率优化+单调栈
		[BZOJ4709][Jsoi2011]柠檬 Description Flute 很喜欢柠檬.它准备了一串用树枝串起来的贝壳,打算用一种魔法把贝壳变成柠檬.贝壳一共有 N (1 ≤ N ≤ 100,0 ... 
- 4709: [Jsoi2011]柠檬
		4709: [Jsoi2011]柠檬 https://www.lydsy.com/JudgeOnline/problem.php?id=4709 分析: 决策单调性+栈+二分. 首先挖掘性质:每个段选 ... 
- 【BZOJ4709】柠檬(动态规划,单调栈)
		[BZOJ4709]柠檬(动态规划,单调栈) 题面 BZOJ 题解 从左取和从右取没有区别,本质上就是要分段. 设\(f[i]\)表示前\(i\)个位置的最大值. 那么相当于我们枚举一个前面的位置\( ... 
随机推荐
- 【SIKIA计划】_06_Unity2D游戏开发-拾荒者笔记
			[新增分类]Animations 动画——Animation——AnimatorControllerPrefabs 预制 [素材导入]unitypackage 素材包Sprites Editor 编辑 ... 
- yum安装lnmp
			python其他知识目录 1.安装LNMP之前要安装EPEL,以便安装源以外的软件,如Nginx,phpMyAdmin等. yum install epel-release 提示:EPEL,即Extr ... 
- CentOS赋予一个普通用户root权限
			http://www.linuxidc.com/Linux/2012-07/64530.htm 
- R语言安装R package的2种方法
			http://www.cnblogs.com/emanlee/archive/2012/12/05/2803606.html 
- Bing词典vs有道词典比对测试报告
			功能篇 核心功能测评:http://www.cnblogs.com/C705/p/4075554.html 细节与用户体验:http://www.cnblogs.com/C705/p/4077112. ... 
- 初学Cocos2dx
			初学cocos2dx Cocos2dx 中的主要概念包括:应用.导演.场景.层.精灵.动画.动作. Cocos2dx里面的主要类 1.CCObject Object Object Object 是co ... 
- 【CS231N】6、神经网络动态部分:损失函数等
			一.疑问 二.知识点 1. 损失函数可视化  损失函数一般都是定义在高维度的空间中,这样要将其可视化就很困难.然而办法还是有的,在1个维度或者2个维度的方向上对高维空间进行切片,例如,随机生成一个权 ... 
- Software Defined Networking(Week 3, part 1)
			Control and Data Plane Seperation 课程地址 Overview 今天正式地学习一个控制与数据平面分离.学习完本节,应该要掌握何为控制和数据平面,了解它们的功能以及好处, ... 
- jquery easyui datagrid  getSelected  getChecked获取选择行数据(勾选)数据
			要想获得上图所选取的元素只能用getChecked getSelected不能进行多个选择,只能单选 /* getSelected取得选中的数据,否则为null */ var user=$(" ... 
- OSG学习:计算纹理坐标
			在很多时候,直接指定纹理坐标是非常不方便的,如曲面纹理坐标,只有少数的曲面(如圆锥.圆柱等)可以在不产生扭曲的情况下映射到平面上,其他的曲面在映射到表面时都会产生一定程度的扭曲.一般而言,曲面表面的曲 ... 
