很自然想到区间 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 Матрёшка 解题报告的更多相关文章

  1. BZOJ 4619 Swap Space 解题报告

    今天是因为David Lee正好讲这个题的类似题,我才做了一下. 本题是world final 2016的一道水…… 题目地址如下 http://www.lydsy.com/JudgeOnline/p ...

  2. BZOJ 2839: 集合计数 解题报告

    BZOJ 2839: 集合计数 Description 一个有\(N\)个元素的集合有\(2^N\)个不同子集(包含空集),现在要在这\(2^N\)个集合中取出若干集合(至少一个),使得 它们的交集的 ...

  3. BZOJ 1367 [Baltic2004]sequence 解题报告

    BZOJ 1367 [Baltic2004]sequence Description 给定一个序列\(t_1,t_2,\dots,t_N\),求一个递增序列\(z_1<z_2<\dots& ...

  4. BZOJ 1044 木棍分割 解题报告(二分+DP)

    来到机房刷了一道水(bian’tai)题.题目思想非常简单易懂(我的做法实际上参考了Evensgn 范学长,在此多谢范学长了) 题目摆上: 1044: [HAOI2008]木棍分割 Time Limi ...

  5. BZOJ 4341 [CF253 Printer] 解题报告

    乍一看这个题好像可以二分优先度搞搞... 实际上能不能这么搞呢...? 我反正不会... 于是开始讲我的乱搞算法: 首先肯定要把任务按照优先度排序. 用一棵在线建点的线段树维护一个时刻是否在工作. 然 ...

  6. BZOJ 4036 [HAOI2015] Set 解题报告

    首先我们不能一位一位的考虑,为什么呢? 你想想,你如果一位一位地考虑的话,那么最后就只有 $n$ 个数字,然而他给了你 $2^n$ 个数字,怎么看都不对劲呀.(我是因为这样子弄没过样例才明白的) 所以 ...

  7. BZOJ 3288 Mato矩阵 解题报告

    这个题好神呀..Orz taorunz 有一个结论,这个结论感觉很优美: $$ans = \prod_{i=1}^{n}\varphi(i)$$ 至于为什么呢,大概是这样子的: 对于每个数字 $x$, ...

  8. BZOJ 4123 [Baltic2015] Hacker 解题报告

    首先,Alice 会选择一个长度为 $\lfloor\frac{n+1}{2}\rfloor$ 的区间,我们把这个长度记为 $len$. 有这么一个结论:令 $F_i$ 为覆盖 $i$ 点的所有长度为 ...

  9. BZOJ 4146 [AMPPZ2014] Divisors 解题报告

    这个题感觉比较小清新... 我们记录每个数出现的次数 $T_i$. 首先依次枚举每个数字,令 $ans = ans + T_i \times (T_i - 1)$,然后枚举这个数的倍数,令 $ans ...

随机推荐

  1. Javascript实现图片无缝滚动

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. 为Debain &&Centos安装dig

    Debain&Ubuntu sudo apt-get install dnsutils Fdeoar&Centos yum install bind-utils

  3. SICP的一些练习题

    1.3 较大两个数之和 (define (MaxSum x y z) (+ (cond ((or (> x y) (> x z)) x) ()) (cond ((or (> y x) ...

  4. C#播放音乐,调用程序

    一:C# 播放音乐 string sound = Application.StartupPath + "/sound/msg.wav"; //Application.Startup ...

  5. B/S一些小知识及常用控件

    一: B/S网页的运行 页面在设计的时候,本身就是一个类.在运行的时间,是一个对象. 其中aspx和aspx.cs是在同一个类下. aspx是主要是负责界面,而aspx.cs主要是负责数据逻辑. 呈现 ...

  6. .Net 指定时间段内定时执行的Windows服务(System.Threading.Thread)

    创建一个Windows服务项目:解决方案(右击)——> 添加 ——> 新建项目——>项目类型选择Windows——>模板选择Windows服务 ,如图: 编写Windows服务 ...

  7. 用JQuery中的Ajax方法获取web service等后台程序中的方法

    用JQuery中的Ajax方法获取web service等后台程序中的方法 1.准备需要被前台html页面调用的web Service,这里我们就用ws来代替了,代码如下: using System; ...

  8. C# IO操作(三)文件编码

    在.net环境下新建一个文本文件(所谓文本文件就是直接可以用记事本打开的文件,直接保存字符串)和在系统中新建一个文本文件的编码是不一样的,.net默认采用UTF-8,而中文操作系统采用的是ANSI.如 ...

  9. Java快速教程

    作者:Vamei     出处:http://www.cnblogs.com/vamei Java是面向对象语言.这门语言其实相当年轻,于1995年才出现,由Sun公司出品.James Gosling ...

  10. POJ 2127 Greatest Common Increasing Subsequence -- 动态规划

    题目地址:http://poj.org/problem?id=2127 Description You are given two sequences of integer numbers. Writ ...