「JSOI2011」柠檬

传送门

斜率优化题。

在优化前,还有一个值得一提的优化:

对于最后的最优分割方案,每一段的两个端点一定是同颜色的,并且作为这一段的 \(s_0\)

证明:如果不作为这一段的 \(s_0\),那么它显然没有贡献,把这一个单独分出来显然更优,直到最后两个端点就一定都是 \(s_0\) ,颜色相同。

那么我们只需要从之前和该点种类相同的位置进行转移即可。

这样就从直接枚举的复杂度 \(O(n^3)\) 优化到了 \(O(n^2)\) ,但还是不够,继续考虑优化。

我们先把转移方程写出来:

\(dp_i\) 表示把前 \(i\) 个取完,且 \(i\) 点作为一段的终点最大收益。

\[dp_i=\max\limits_{1\le j \le i,a_j=a_i}\left\{dp_{j-1}+s_i(p_i-p_j+1)^2\right\}
\]

\(p_i\) 表示第 \(i\) 个点是种类为 \(s_i\) 的第 \(p_i\) 个点。

根据斜率优化的一些做法,我们可以把式子化成这样:

\(p_i\times 2p_js_j+dp_i-s_i(p_i+1)^2=dp_{j-1}-2a_jp_j+a_jp_j^2\)

设 \(x_i = 2s_ip_i,y_i=dp_{i-1}-2s_ip_i+s_ip_i^2\)

\(p_ix_j+dp_i-s_i(p_i+1)^2=y_j\)

因为要让 \(dp_i\) 最大化,所以我们对每一种颜色都用单调栈维护一个上凸包,这样才能满足决策单调性。

注意一点细节:

因为我们的转移点 \(j\) 的范围是 \([1,i]\) 的,而我们再插入 \(j\) 这个点时只有 \(dp_{j-1}\) 这个信息,为了能取到 \(dp_{i-1}\) ,我们需要在寻找最优转移点之前就把 \(i\) 加入单调栈。

参考代码:

#include <cstdio>
#include <vector>
#define rg register
#define int long long
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
using namespace std;
template < class T > inline void read(T& s) {
s = 0; int f = 0; char c = getchar();
while ('0' > c || c > '9') f |= c == '-', c = getchar();
while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
s = f ? -s : s;
} const int _ = 1e5 + 5; int n, s[_], p[_], pos[_], dp[_];
vector < int > stk[_]; inline int X(int i) { return 2 * s[i] * p[i]; } inline int Y(int i) { return dp[i - 1] - 2 * s[i] * p[i] + s[i] * p[i] * p[i]; } inline double slope(int i, int j) { return (double) (Y(i) - Y(j)) / (X(i) - X(j)); } signed main() {
#ifndef ONLINE_JUDGE
file("cpp");
#endif
read(n);
for (rg int i = 1; i <= n; ++i) read(s[i]), p[i] = ++pos[s[i]];
#define A stk[c][stk[c].size() - 2]
#define B stk[c][stk[c].size() - 1]
for (rg int i = 1; i <= n; ++i) {
int c = s[i];
while (stk[c].size() > 1 && slope(A, B) < slope(A, i)) stk[c].pop_back();
stk[c].push_back(i);
while (stk[c].size() > 1 && slope(A, B) < p[i]) stk[c].pop_back();
int j = stk[c].back();
dp[i] = dp[j - 1] + s[i] * (p[i] - p[j] + 1) * (p[i] - p[j] + 1);
}
#undef A
#undef B
printf("%lld\n", dp[n]);
return 0;
}

「JSOI2011」柠檬的更多相关文章

  1. 「JSOI2011」任务调度

    「JSOI2011」任务调度 传送门 一开始还在想写平衡树,看到 \(\text{TRANS}\) 操作后就晓得要用可并堆了. 这题好像就是个可并堆的板子题??? ADD 直接往对应的对里面加元素 D ...

  2. 「JSOI2011」棒棒糖

    「JSOI2011」棒棒糖 传送门 双倍经验 考虑主席树做法. 对于当前的主席树节点,如果 \(\le mid\) 的个数足够就往左边走,否则就尝试往右边走,都不行就返回 \(0\). 参考代码: # ...

  3. 「JSOI2011」分特产

    「JSOI2011」分特产 传送门 计数题. 考虑容斥掉每人至少一个的限制. 就直接枚举至少有多少人没有分到特产,然后剩下的随便分. \[Ans = \sum_{i = 0}^n (-1)^i {n ...

  4. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  5. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  6. JavaScript OOP 之「创建对象」

    工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...

  7. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

  8. 「JavaScript」四种跨域方式详解

    超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...

  9. 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management

    写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...

随机推荐

  1. 8.10-DayT3游走(wander)

    题目大意 lue.. 题解 先跑一遍tarjan缩点,在新图中加入两个强连通分量之间的边,则此图为一个有向无环图(DAG).则最终答案为1点所在的强连通分量或包括1点的几个强连通分量的点数之和. 如果 ...

  2. Bugku-CTF分析篇-weblogic(黑客攻击了Weblogic应用,请分析攻击过程,找出Weblogic的主机名。)

    weblogic 黑客攻击了Weblogic应用,请分析攻击过程,找出Weblogic的主机名. flag格式:flag{} Tip:主机名为十六进制.  

  3. ModelSerializer,序列化与反序列化整合

    复习 """ 1.解析模块:全局局部配置 REST_FRAMEWORK = { # 全局解析类配置 'DEFAULT_PARSER_CLASSES': [ 'rest_f ...

  4. 截取字符,超出的用省略号代替js实现 substring

    可用到截取文字过多的问题,取0到6之间的字符,不包含6title.substring(0,6)+'...';

  5. 微信个人支付接口---YunGouOS 1.1.3 版本发布,新增个人微信/支付宝收款接口

    软件接口  https://www.oschina.net/news/113305/yungouos-1-1-3-released 文档说明  https://www.oschina.net/p/Yu ...

  6. LPR-贷款市场报价利率

    贷款市场报价利率(Loan Prime Rate)介绍: 贷款市场报价利率(Loan Prime Rate,简称LPR)是商业银行对其最优质客户执行的贷款利率,其他贷款利率可在此基础上加减点生成.贷款 ...

  7. python连接Oracle的方式以及过程中遇到的问题

    一.库连接步骤 1.下载cx_Oracle模块 下载步骤 工具 pycharm :File--->右键setting--->找到Project Interpreter  -----> ...

  8. 本地mongodb数据库导出到远程数据库中

    把本地Mongodb中的数据导入(批量插入)到服务器的数据库中 1.导出数据: mongoexport -d admin -c users -o outdatafile.dat 选项解释: -d 指明 ...

  9. net core调用MimeKit发送QQ邮件

    一.在QQ邮箱内申请授权码,具体参考请官方文档 二.具体代码 public void TestSendMailDemo() { MimeMessage message = new MimeMessag ...

  10. for语句处理多维数组

    看C++Primer第三章看到的,记录一下. 下面这段代码非法,因为row指向的是每一行的一个大小为10的一维数组,默认转为指针,即row其实是一个int*类型的指针,显然内层循环就出错了 int a ...