BZOJ 3971 Матрёшка 解题报告
很自然想到区间 DP。
设 $Dp[i][j]$ 表示把区间 $[i, j]$ 内的套娃合并成一个所需要的代价,那么有:
- $Dp[i][i] = 0$
- $Dp[i][j] = min\{Dp[i][k] + Dp[k + 1][j] + Merge([i, k], [k + 1, j])\} (i \le k < j)$
于是问题在于算 $Merge([a, b], [c, d])$。
我们考虑一下:区间 $[a, b]$ 内的哪些套娃是需要打开的:
是不是 $[a, b]$ 中所有大于 $[c, d]$ 中最小的套娃都需要打开,来装 $[c, d]$ 中最小的套娃呢?
$[c, d]$ 同理。
于是我们可以预处理 $Sum[i][x]$ 为在前 $i$ 个套娃中,大小 $\le x$ 的套娃的个数,
那么就可以 $O(1)$ 地算 $Merge([a, b], [c, d])$ 了。
有一个问题,如果在 $[a, b]$、$[c, d]$ 中有相同大小的套娃怎么办?
不着急,先往下看。
处理完 $Dp[i][j]$ 后,我们再设立一个 $F[i]$ 表示把前 $i$ 个套娃装成若干个完好的套娃集所需代价的最小值,那么就有:
- $F[i] = min(F[j] + Dp[j + 1][i]) (mex([j + 1, i]) = i - j + 1)$
- $mex([u, v]) = min(x) (x\notin \{A_u, A_{u+1}, \dots, A_v\})$
当然,如果不能找到合法的转移点,那么令 $F[i] = INF$。
然后对于一个合法的方案,不可能出现相同大小的套娃被装进同一个套娃内的情况,
所以 $[a, b]$、$[c, d]$ 中有相同大小的套娃的话,那么这个区间一定不合法,所以我们大可不必考虑那么多了。
于是最后看 $F[n]$ 就可以了。令 $M = max\{A_i\}$
时间复杂度 $O(n^3 + n^2M)$,空间复杂度 $O(n^2 + nM)$。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 500 + 5
#define INF 593119681 int n, Max;
int A[N], _Dp[N], T[N];
int Sum[N][N], Dp[N][N], Mex[N][N], Min[N][N]; inline void Prepare()
{
for (int i = ; i <= n; i ++)
Sum[i][A[i]] ++;
for (int i = ; i <= n; i ++)
for (int j = ; j <= Max; j ++)
Sum[i][j] += Sum[i][j - ] + Sum[i - ][j] - Sum[i - ][j - ]; for (int i = ; i <= n; i ++)
{
for (int j = ; j <= Max; T[j ++] = ) ;
for (int j = i; j <= n; j ++)
{
T[A[j]] ++;
for (Mex[i][j] = ; T[Mex[i][j]]; Mex[i][j] ++) ;
Min[i][j] = i == j ? A[i] : min(Min[i][j - ], A[j]);
}
}
} inline int Calc(int l, int mid, int r)
{
int min_1 = Min[l][mid], res = Sum[r][Max] - Sum[mid][Max] - Sum[r][min_1] + Sum[mid][min_1];
min_1 = Min[mid + ][r], res += Sum[mid][Max] - Sum[l - ][Max] - Sum[mid][min_1] + Sum[l - ][min_1];
return res;
} int main()
{
#ifndef ONLINE_JUDGE
freopen("3971.in", "r", stdin);
freopen("3971.out", "w", stdout);
#endif scanf("%d", &n);
for (int i = ; i <= n; i ++)
{
scanf("%d", A + i);
Max = max(Max, A[i]);
}
Prepare();
for (int len = ; len < n; len ++)
for (int s = ; s + len <= n; s ++)
{
int i = s, j = s + len;
if (i == j) Dp[i][j] = ;
else
{
Dp[i][j] = INF;
for (int k = i; k < j; k ++)
Dp[i][j] = min(Dp[i][j], Dp[i][k] + Dp[k + ][j] + Calc(i, k, j));
}
}
for (int i = ; i <= n; i ++) _Dp[i] = INF;
for (int i = ; i <= n; i ++)
for (int j = ; j < i; j ++)
if (Mex[j + ][i] == i - j + )
_Dp[i] = min(_Dp[i], _Dp[j] + Dp[j + ][i]);
if (_Dp[n] >= INF) puts("Impossible");
else printf("%d\n", _Dp[n]); #ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return ;
}
3971_Gromah
BZOJ 3971 Матрёшка 解题报告的更多相关文章
- BZOJ 4619 Swap Space 解题报告
今天是因为David Lee正好讲这个题的类似题,我才做了一下. 本题是world final 2016的一道水…… 题目地址如下 http://www.lydsy.com/JudgeOnline/p ...
- BZOJ 2839: 集合计数 解题报告
BZOJ 2839: 集合计数 Description 一个有\(N\)个元素的集合有\(2^N\)个不同子集(包含空集),现在要在这\(2^N\)个集合中取出若干集合(至少一个),使得 它们的交集的 ...
- BZOJ 1367 [Baltic2004]sequence 解题报告
BZOJ 1367 [Baltic2004]sequence Description 给定一个序列\(t_1,t_2,\dots,t_N\),求一个递增序列\(z_1<z_2<\dots& ...
- BZOJ 1044 木棍分割 解题报告(二分+DP)
来到机房刷了一道水(bian’tai)题.题目思想非常简单易懂(我的做法实际上参考了Evensgn 范学长,在此多谢范学长了) 题目摆上: 1044: [HAOI2008]木棍分割 Time Limi ...
- BZOJ 4341 [CF253 Printer] 解题报告
乍一看这个题好像可以二分优先度搞搞... 实际上能不能这么搞呢...? 我反正不会... 于是开始讲我的乱搞算法: 首先肯定要把任务按照优先度排序. 用一棵在线建点的线段树维护一个时刻是否在工作. 然 ...
- BZOJ 4036 [HAOI2015] Set 解题报告
首先我们不能一位一位的考虑,为什么呢? 你想想,你如果一位一位地考虑的话,那么最后就只有 $n$ 个数字,然而他给了你 $2^n$ 个数字,怎么看都不对劲呀.(我是因为这样子弄没过样例才明白的) 所以 ...
- BZOJ 3288 Mato矩阵 解题报告
这个题好神呀..Orz taorunz 有一个结论,这个结论感觉很优美: $$ans = \prod_{i=1}^{n}\varphi(i)$$ 至于为什么呢,大概是这样子的: 对于每个数字 $x$, ...
- BZOJ 4123 [Baltic2015] Hacker 解题报告
首先,Alice 会选择一个长度为 $\lfloor\frac{n+1}{2}\rfloor$ 的区间,我们把这个长度记为 $len$. 有这么一个结论:令 $F_i$ 为覆盖 $i$ 点的所有长度为 ...
- BZOJ 4146 [AMPPZ2014] Divisors 解题报告
这个题感觉比较小清新... 我们记录每个数出现的次数 $T_i$. 首先依次枚举每个数字,令 $ans = ans + T_i \times (T_i - 1)$,然后枚举这个数的倍数,令 $ans ...
随机推荐
- 我的第二篇--nginx安装问题之路径问题
这几天还是一直在搭建nginx,并且要在nginx的基础之上配置naxsi(WAF防火墙)并使它生效,但是随之而来的问题也会有很多,也许因为我是个新手,所以遇到的问题要多,不解的问题也要很多,不知道又 ...
- Executor 和Executors
Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具.真正的线程池接口是ExecutorService. 下面这张图完整描述了线程 ...
- 对css float 浮动的学习心得
css float浮动详解 @(css float)[hasLayout|clear float|妙瞳] css float的定义和用法 float 属性定义元素在哪个方向浮动.以往这个属性总应用于图 ...
- RabbitMQ 原文译04--路由
在前一篇文章中我们构建了一个简单的日志系统,我们可以向多个接受者广播消息. 在这篇文章我,我们将要添加一些功能使得针对部分消息的接受成为可能,例如我们只对错误的消息进行磁盘记录,同时又可以把所有的消息 ...
- 如何让Div层悬浮在Flash Object对象之上(转载)
今天有个用户,门户右上角的倒三角登陆小按钮在他的电脑上无法显示,他用的笔记本屏幕较小,宽度正好显示出页面内容,经查看,门户页眉使用的为flash对象. 大家都知道,如果想让某个图片或者Div层悬浮在别 ...
- webview中java与js交互
WebView提供了在Android应用中展示网页的强大功能.也是目前Hybird app的大力发展的基础.作为Android系统的一个非常重要的组件,它提供两方面的强大的能力:对HTML的解析,布局 ...
- IO流详解(半教材类型)
这两天学习了IO流,整理了一些理论知识点,仅供参考. java流概述 一 流 从操作系统层面和文件系统,数据保存相关的是所有语言都具备的一个基本功能,java专门开发了一个包:java.io.*;ja ...
- IOS- 最简单的反向传值- block
block 常用于反向传值 声明 返回值类型 (^block)(参数列表) 调用 闭包的名字=^(参数列表){}: 闭包的名字(): 如: void(^aaaaa)(int num,NSString ...
- 在不同版本的 IIS 上使用 ASP.NET MVC
ASP.NET MVC Framework 依赖于 URL 路由.为了利用 URL 路由,可能不得不在 Web 服务器上执行额外的配置步骤.这些步骤取决于 Internet Information S ...
- windows10和ubuntu16.04双系统下时间不对的问题
最近装了windows10和ubuntu16.04双系统,仍然出现了喜闻乐见的老问题,装完后,在windows下时区不对,之前的老办法是: sudo gedit /etc/default/rcS ut ...