题目描述

一道简单DP优化调了好久qwq

首先分析题目,发现每次从一边取贝壳是完全没用的,此题本质就是将区间分成数个区间,使区间价值和最大。

可以发现一个性质,那就是最优解的每个区间的两端点一定相同且为选取的\(s_0\)。因为如果区间两端点的值不同,那么完全可以将多余的值分为另一个区间使价值和更大。

所以可以写出简单的dp式:

\(dp[i] = max(dp[j-1] + s[i] * (sum[i] - sum[j]+1)^2) \quad (s[j] == s[i])\)

其中\(sum[i]\)为1…i中\(s[i]\)的个数,可以简单的\(O(1)\)维护,所以总复杂度\(O(n^2)\)

观察单调性,发现对于决策a,b\((a<b)\)如果在k处a比b优,那么在k之后a也一定比b优,而k可以通过二分\(O(log_n)\)求出

所以可以使用单调栈维护最优决策,对于每次决策,如果栈顶不优了就弹出栈顶。同时,为了维护栈的单调性,每次入栈z时,如果z与栈顶元素的分界点\(k_1\)比栈顶与栈顶的下一个元素的分界点\(k_2\)靠后,那么便可以弹出栈顶元素。

/**************************************************************
Problem: 4709
User: liuxinyuan
Language: C++
Result: Accepted
Time:328 ms
Memory:3144 kb
****************************************************************/ #include <algorithm>
#include <cstdio>
#include <iostream>
#include <stack>
#include <vector>
#define gc getchar
#define il inline
#define re register
#define LL long long
#define mid(l, r) (((l) + (r)) >> 1)
#define sqr(x) (1ll * (x) * 1ll * (x))
#define m_p(x, y) make_pair(x, y)
using namespace std;
template <typename T>
void rd(T &s)
{
s = 0;
bool p = 0;
char ch;
while (ch = gc(), p |= ch == '-', ch < '0' || ch > '9')
;
while (s = s * 10 + ch - '0', ch = gc(), ch >= '0' && ch <= '9')
;
s *= (p ? -1 : 1);
}
template <typename T, typename... Args>
void rd(T &s, Args &... args)
{
rd(s);
rd(args...);
}
const int MAXM = 10005;
const int MAXN = 100050;
vector<int> sta[MAXM];
LL dp[MAXN];
int s[MAXN];
int cnt[MAXM], sum[MAXN];
int n;
il LL cal(int x, int y)
{
return dp[x - 1] + s[x] * 1ll * y * 1ll * y;
}
int lower(int a, int b)
{
int v = s[a];
int l = 1, r = cnt[v], ans = cnt[v] + 1;
while (l <= r)
{
int m = mid(l, r);
if (cal(a, m - sum[a] + 1) >= cal(b, m - sum[b] + 1))
ans = m,
r = m - 1;
else
l = m + 1;
}
return ans;
}
int main()
{
int v;
rd(n);
for (int i = 1; i <= n; ++i)
{
rd(s[i]);
sum[i] = ++cnt[s[i]];
}
for (int i = 1; i <= n; ++i)
{
v = s[i];
while (sta[v].size() >= 2 && lower(sta[v][sta[v].size() - 2], sta[v][sta[v].size() - 1]) < lower(sta[v][sta[v].size() - 1], i))
sta[v].pop_back();
sta[v].push_back(i);
while (sta[v].size() >= 2 && lower(sta[v][sta[v].size() - 2], sta[v][sta[v].size() - 1]) <= sum[i])
sta[v].pop_back();
dp[i] = cal(sta[v][sta[v].size() - 1], sum[i] - sum[sta[v][sta[v].size() - 1]] + 1);
// cout << i << " " << sta[v][sta[v].size() - 1] << endl;
}
// for (int i = 1; i <= n; ++i)
printf("%lld", dp[n]);
return 0;
}

题解 BZOJ4709的更多相关文章

  1. bzoj4709: [Jsoi2011]柠檬 斜率优化

    题目链接 bzoj4709: [Jsoi2011]柠檬 题解 斜率优化 设 \(f[i]\) 表示前 \(i\)个数分成若干段的最大总价值. 对于分成的每一段,左端点的数.右端点的数.选择的数一定是相 ...

  2. 【BZOJ4709】柠檬(动态规划,单调栈)

    [BZOJ4709]柠檬(动态规划,单调栈) 题面 BZOJ 题解 从左取和从右取没有区别,本质上就是要分段. 设\(f[i]\)表示前\(i\)个位置的最大值. 那么相当于我们枚举一个前面的位置\( ...

  3. 【BZOJ4709】[Jsoi2011]柠檬 斜率优化+单调栈

    [BZOJ4709][Jsoi2011]柠檬 Description Flute 很喜欢柠檬.它准备了一串用树枝串起来的贝壳,打算用一种魔法把贝壳变成柠檬.贝壳一共有 N (1 ≤ N ≤ 100,0 ...

  4. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  5. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  6. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  7. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  8. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  9. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

随机推荐

  1. uTools - 你的生产力工具集

    工具介绍 uTools是一个极简.插件化.跨平台的现代化桌面软件.通过自由选配丰富的插件,打造你得心应手的工具集合. 通过快捷键(默认alt+space)就可以快速呼出这个搜索框.它相当聪明,可以支持 ...

  2. odoo12数据库自动化备份

    数据库自动备份模块地址 https://github.com/Yenthe666/auto_backup#8.0 目前支持8以上的版本 odoo12的配置步骤 1.下载模块到自己的模块目录 2.登录o ...

  3. Nginx配置多个域名指向不同的端口

    一.前言 很多时候我们都会在同一个服务器上部署多个项目,我们有多个域名的情况下,怎么样使不同的域名都通过80端口来访问呢?打个比方说,现在有2个域名,分别是:tessai.cn 和 admin.tes ...

  4. xctf-web supersqli

    单引号注入,用order by查到了两个column.用union select的时候发现select关键字被过滤了 用分号尝试堆叠注入显示出了两张表 分别查询字段 flag在表19198109311 ...

  5. ken桑带你读源码 之scrapy scrapy\extensions

    logstats.py 爬虫启动时 打印抓取网页数   item数 memdebug.py 爬虫结束 统计还被引用的内存 也就是说gc 回收不了的内存   memusage.py 监控爬虫 内存占用  ...

  6. Java线程池ThreadPoolExecutor面试总结思维导图速记

    优点 降低资源消耗,通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 提高响应速度,当任务到达时,可以不需要等待线程创建就能立即执行. 提高线程的可管理性 类关系 接 Executor 一个无返 ...

  7. list 和 [ ] 的功能不相同

    对于一个对象: list(对象) 可以进行强制转换 [对象] 不能够进行强制转换,只是在外围加上 [ ] 列表推导式中相同   2020-05-06

  8. Python os.rmdir() 方法

    概述 os.rmdir() 方法用于删除指定路径的目录.仅当这文件夹是空的才可以, 否则, 抛出OSError.高佣联盟 www.cgewang.com 语法 rmdir()方法语法格式如下: os. ...

  9. PHP date_offset_get() 函数

    ------------恢复内容开始------------ 实例 返回奥斯陆(在欧洲挪威)冬天和夏天相对于 UTC 的以秒计的时区偏移量: <?php$winter=date_create(& ...

  10. PHP symlink() 函数

    定义和用法 symlink() 函数创建一个从指定名称连接的现存目标文件开始的符号连接. 如果成功,该函数返回 TRUE.如果失败,则返回 FALSE. 语法 symlink(target,link) ...