前言

\(csp\)时发现自己做过类似这道题的题目 : P4954 [USACO09Open] Tower of Hay 干草塔

然后回忆了差不多\(15min\)才想出来。。。

然后就敲了\(88pts\)的部分分。当时的内存是\(950MB\)左右,写一个高精就炸内存了。

题目

2048 年,第三十届 CSP 认证的考场上,作为选手的小明打开了第一题。这个题的样例有 \(n\) 组数据,数据从 \(1 \sim n\) 编号,\(i\) 号数据的规模为 \(a_i\)。

小明对该题设计出了一个暴力程序,对于一组规模为 \(u\) 的数据,该程序的运行时间为 \(u^2\)。然而这个程序运行完一组规模为 \(u\) 的数据之后,它将在任何一组规模小于 \(u\) 的数据上运行错误。样例中的 \(a_i\) 不一定递增,但小明又想在不修改程序的情况下正确运行样例,于是小明决定使用一种非常原始的解决方案:将所有数据划分成若干个数据段,段内数据编号连续,接着将同一段内的数据合并成新数据,其规模等于段内原数据的规模之和,小明将让新数据的规模能够递增。

也就是说,小明需要找到一些分界点 \(1 \leq k_1 \lt k_2 \lt \cdots \lt k_p \lt n\),使得

\[\sum_{i=1}^{k_1} a_i \leq \sum_{i=k_1+1}^{k_2} a_i \leq \cdots \leq \sum_{i=k_p+1}^{n} a_i
\]

注意 \(p\) 可以为 \(0\) 且此时 \(k_0 = 0\),也就是小明可以将所有数据合并在一起运行。

小明希望他的程序在正确运行样例情况下,运行时间也能尽量小,也就是最小化

\[(\sum_{i=1}^{k_1} a_i)^2 + (\sum_{i=k_1+1}^{k_2} a_i)^2 + \cdots + (\sum_{i=k_p+1}^{n} a_i)^2
\]

小明觉得这个问题非常有趣,并向你请教:给定 \(n\) 和 \(a_i\),请你求出最优划分方案下,小明的程序的最小运行时间。

思路:

假设我们现在已经划分为三个部分\(x,y,z\)满足\(x\leq y\leq z\),那么显然是有

\[x^2+y^2+z^2<x^2+(y+z)^2
\]

所以我们肯定要做到能分就分

但是贪心选取肯定是错误的。样例一明显就指出了错误。

考虑\(dp\)。设\(f[i]\)表示我们划分\(1\sim i\)的所有数,以\(i\)为最后一个区块的情况下,最后一个区块的最小长度。

那么枚举一个\(j\),明显有

\[f[i]=min(\sum^{i}_{k=j}a_k)\ \ \ (\sum^{i}_{k=j}a_k\geq f[j])
\]

由于\(\sum^{i}_{k=j}a_k\)满足单调性,所以肯定选择尽量大的\(j\)来转移。

如果\(j\)可以转移到\(i\),那么转移的同时可以求出划分的费用

\[ans[i]=ans[j-1]+(\sum^{i}_{k=j}a_k)^2
\]

这样我们就得到了一个\(O(n^2)\)的算法,可以得到\(64pts\)的高分。

我们发现,转移的条件\(\sum^{i}_{k=j}a_k\geq f[j]\)其实就是\(\sum^i_{k=1}a_k-\sum^i_{k=j}a_k\geq f[j]\),移项就得到了\(\sum^i_{k=1}a_k\geq f[j]+\sum^i_{k=j}a_k\)

我们发现,在做了前缀和之后,上式等号左边只与\(i\)有关,等号右边只与\(j\)有关。同时我们又要满足选择尽量大的\(j\)来转移,所以就可以维护一个单调队列装\(f[j]+\sum^i_{k=j}a_k\)进行转移。

但是我们每次要选择的是满足\(\sum^i_{k=1}a_k\geq f[j]+\sum^i_{k=j}a_k\)的尽量大\(j\)进行转移,而不是单纯的最小的\(\sum^i_{k=1}a_k\geq f[j]+\sum^i_{k=j}a_k\)转移。所以我们每次要不断弹出队头,知道队头不再满足\(\sum^i_{k=1}a_k\geq f[j]+\sum^i_{k=j}a_k\)。此时将最后一次弹出的元素再从头部插入进行转移。这样就保证了每次选择\(j\)最大的满足条件的元素进行转移。容易证明,弹出的元素不会对后面的转移产生影响。

这样每个元素最多进入队列1次,时间复杂度\(O(n)\)。

这样我们就得到了\(88pts\)的高分。

对于\(type=1\)的数据点需要使用高精,但是由于\(O(n)\)的算法我们的内存已经使用了\(950MB\),所以几乎没有空间来敲高精。

所以此时就只能用csp不允许使用的__int128了

我们将\(ans\)改为\(\_\_int128\)类型,是可以存下最终答案的。

然后我就愉快的T了。



在尝试过所有我知道的化学性卡常后,样例三依然需要\(2.4s+\)才可以跑过。

所以此时就只能用csp不允许使用的Ofast了

物理性卡常\(nb\)!样例最终可以在\(0.85s\)左右跑过。

然后我就愉快的MLE了。



经过输出后,\(ans,f,sum\)三个数组加起来是\(1200+MB\)。将近\(200MB\)的差距,只能考虑删除一个数组了。

\(ans\)和\(sum\)是肯定无法删除的,而\(f\)我们发现,在转移时是等于\(sum[i]-sum[last]\)的,其中\(last\)直可以转移的最大的\(j\)。

所以我们考虑直接用\(sum\)数组来表示出\(f\)数组。这样我们往单调队列插入时就要插入\(i,f_i+sum_i\)两维,因为后者在去掉\(f\)数组后是没办法算出来的。

最终还是以\(1.38s,804.98MB\)过了这道题。但是在\(csp\)时是不允许用\(\_\_int128\)和\(Ofast\)的,所以其实这份代码无论是时间还是空间都是过不去的

代码:

#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include <queue>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#define mp make_pair
using namespace std;
typedef long long ll; const int N=40000010,MOD=(1<<30),M=100010;
int n,x,type,cnt,id;
ll d,xx,yy,zz,m,sum[N],b[4],p[M],l[M],r[M];
__int128 ans[N];
pair<int,ll> last;
char ch;
deque<pair<int,ll> > q; inline ll read()
{
d=0; ch=getchar();
while (!isdigit(ch)) ch=getchar();
while (isdigit(ch))
d=(d<<3)+(d<<1)+ch-48,ch=getchar();
return d;
} inline void write(__int128 x)
{
if (x>9) write(x/10);
putchar(x%10+48);
} inline ll Get(int i)
{
int id=(i-1)%3+1;
if (i>2 && id==1) b[1]=(xx*b[3]+yy*b[2]+zz)%MOD;
if (i>2 && id==2) b[2]=(xx*b[1]+yy*b[3]+zz)%MOD;
if (i>2 && id==3) b[3]=(xx*b[2]+yy*b[1]+zz)%MOD; //减少模运算次数
if (i>p[cnt]) cnt++;
return (b[id]%(r[cnt]-l[cnt]+1))+l[cnt];
} int main()
{
scanf("%d%d",&n,&type);
if (type)
{
xx=read(); yy=read(); zz=read(); b[1]=read(); b[2]=read(); m=read();
for (int i=1;i<=m;i++)
p[i]=read(),l[i]=read(),r[i]=read();
}
q.push_back(mp(0,0));
for (register int i=1;i<=n;i++)
{
sum[i]=sum[i-1]+(type?Get(i):read());
while (q.size() && sum[i]>=q.front().second)
{
last=q.front();
q.pop_front();
}
q.push_front(last);
int pos=last.first;
ans[i]=ans[pos]+(__int128)(sum[i]-sum[pos])*(sum[i]-sum[pos]);
while (q.size() && q.back().second>=sum[i]-sum[pos]+sum[i]) q.pop_back();
q.push_back(mp(i,sum[i]-sum[pos]+sum[i]));
}
write(ans[n]);
return 0;
}

【CSP-S 2019】【洛谷P5665】划分【单调队列dp】的更多相关文章

  1. 洛谷 U4792 Acheing 单调队列

    U4792 Acheing 5通过 43提交 题目提供者Acheing 标签 难度尚无评定 提交 最新讨论 暂时没有讨论 题目背景 题目并没有什么含义,只是想宣传一下自己的博客,Acheing.com ...

  2. 【洛谷】【单调队列】P2032 扫描

    [题目描述:] 有一个 1 ∗ n 的矩阵,有 n 个正整数. 现在给你一个可以盖住连续的 k 的数的木板. 一开始木板盖住了矩阵的第 1 ∼ k 个数,每次将木板向右移动一个单位,直到右端与第 n ...

  3. 滑动窗口-洛谷T1866(单调队列)

    咕咕咕 单调队列板子题 一.基本 1.单调队列: 特殊的双端队列,内部元素.分为最大队列(单调递增)和最小队列(单调递减)两种 二.应用 本题中:大部分单调队列优化的动态规划问题都和定长连续子区间的最 ...

  4. 洛谷P2827 蚯蚓(单调队列)

    题意 初始时有$n$个蚯蚓,每个长度为$a[i]$ 有$m$个时间,每个时间点找出长度最大的蚯蚓,把它切成两段,分别为$a[i] * p$和$a[i] - a[i] * p$,除这两段外其他的长度都加 ...

  5. P1091 合唱队形题解(洛谷,动态规划LIS,单调队列)

    先上题目 P1091 合唱队形(点击打开题目) 题目解读: 1.由T1​<...<Ti​和Ti​>Ti+1​>…>TK​可以看出这题涉及最长上升子序列和最长下降子序列 2 ...

  6. 【洛谷】【单调栈】P4333 [COI2007] Patrik

    --接上一篇题解,[洛谷][单调栈]P1823音乐会的等待 关于题目大意在上一篇题解里已经说清楚了,这里不再多阐述 想看题目->戳这里 [算法分析:] 在对元素a进行判断时,如果它与栈顶元素相等 ...

  7. 洛谷 P5279 - [ZJOI2019]麻将(dp 套 dp)

    洛谷题面传送门 一道 dp 套 dp 的 immortal tea 首先考虑如何判断一套牌是否已经胡牌了,考虑 \(dp\)​​​​​.我们考虑将所有牌按权值大小从大到小排成一列,那我们设 \(dp_ ...

  8. POJ 3017 单调队列dp

    Cut the Sequence Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8764   Accepted: 2576 ...

  9. [TyvjP1313] [NOIP2010初赛]烽火传递(单调队列 + DP)

    传送门 就是个单调队列+DP嘛. ——代码 #include <cstdio> ; , t = , ans = ~( << ); int q[MAXN], a[MAXN], f ...

  10. zstu 4237 马里奥的求救——(单调队列DP)

    题目链接:http://oj.acm.zstu.edu.cn/JudgeOnline/problem.php?id=4237 这题可以转化为每次可以走g~d+x步,求最大分数,且最大分数的步数最少. ...

随机推荐

  1. 嵌入式02 STM32 实验02 端口输入输出各4种模式

    GPIO(General-purpose input/output 通用目的输入/输出端口) 电压(A模拟量)与电平(D数字量) GPIO 8种工作模式(输入四种.输出四种) 1.GPIO_Mode_ ...

  2. 【Linux】一步一步学Linux——Bash常用快捷键(11)

    目录 00. 目录 01. 编辑命令 02. 搜索命令 03. 控制命令 04. 其它 05. 参考 00. 目录 @ 生活在 Bash Shell 中,熟记以下快捷键,将极大的提高你的命令行操作效率 ...

  3. xxx商城之架构和功能简述

      XXX商城项目简介        XXX商城项目是一套做特卖的电商系统,包括前台商城系统(App.微信版.小程序版.H5版)及后台管理系统,基于SpringBoot+SpringDataJpa+S ...

  4. TypeScript之泛型

    什么是泛型,有什么用? 泛型字面意思就是广泛的类型,怎么样才算广泛呢?当然是能变的最广泛嘛, 所谓泛型就是类型的变量写法,让你的变量的类型是动态可变的,应用场景如官方文档描述的例子: 一个函数,输入什 ...

  5. JavaScript是单线程还是多线程(转)

    多线程要考虑线程之间的资源抢占,死锁,冲突之类一系列问题.JavaScript作为一门客户端脚本,貌似没有多线程的一些列问题.那么JavaScript是单线程还是多线程?通过查资料总结了JavaScr ...

  6. 生物网络,RNA 与疾病关联分析

    题目: 大数据时代下基于网络算法和机器学习的非编码RNA 相关预测研究摘要:最近越来越多的生物实验表明非编码RNA 具有非常重要的生物学功能,参与细胞中的多项重要生命活动,调控许多基本且重要的生物过程 ...

  7. js 简单的滑动4

    js 简单的滑动教程(四)   作者:Lellansin 转载请标明出处,谢谢 在大概的了解滑动的基本原理和怎么去实现之后,现在我们将更深入的去讨论js的滑动. 相信细心的朋友应该已经发现了,在本教程 ...

  8. 【洛谷 P5341】 [TJOI2019]甲苯先生和大中锋的字符串(后缀自动机)

    题目链接 建出\(sam\),求出parent tree上每个点的\(endpos\)集合大小. 如果等于\(k\),说明到达这个点的都可以.给\((len[fa(i)],len[i]]\)的\(cn ...

  9. Java中BIO和NIO

    同步/异步.阻塞/非阻塞概念 同步异步 同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication) 同步:在发出一个 ...

  10. mySql入门-(二)

    最近刚刚开始学习Mysql,然而学习MySql必经的一个过程就是SQL语句,只有按照文档从头开始学习SQL语句.学习的过程是痛苦的,但是学完的成果是甘甜的. SQL 语法 所有的 SQL 语句都以下列 ...