很自然想到区间 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开发中的封装模式(转)

    var bgAuido={ audio : pingfan.$$('audio'), audioBtn : pingfan.$$('audioBtn'), init : function(){ var ...

  2. Eclipse中的TreeViewer类和ListViewer类

    TreeViewer和TableViewer在使用上还是有很多相似之处.TreeViewer中冶有TableViewer中的过滤器和排序器.具体使用看TableViewer中的使用. 和Table有J ...

  3. 【转】物业管理与移动互联网科技|微信公众平台,物业app,物业O2O

    [导语]当下,物业管理行业正在接受新科技浪潮的冲击和洗礼,业界企业纷纷探索物业服务的新发展模式.云服务.微社区.微信公众平台.app等,这些本来陌生的词汇在物业管理行业变得耳熟能详.在借助科技手段拓展 ...

  4. (转)MySQL数据表中带LIKE的字符匹配查询

    MySQL数据表中带LIKE的字符匹配查询 2014年07月15日09:56    百科369 MySQL数据表中带LIKE的字符匹配查询 LIKE关键字可以匹配字符串是否相等. 如果字段的值与指定的 ...

  5. Html5时钟的实现

    最近准备把自己的博客装修一下,首先,先为自己设计一个时钟吧,希望博客园能够尽快发放给我使用js的权限! 自从看见了苹果设计的那款因为侵权而赔钱了时钟,我就决定我的时钟一定是要参考这个来设计了! 不得不 ...

  6. 【Excel VBA】金额大写转换

    =IF(ROUND(A1,2)<0,"金额为负无效",IF(ROUND(A1,2)=0,"零元",IF(ROUND(A1,2)<1,"&q ...

  7. springmvc前后端传值总结

    1      前端向后端传参 1.1    普通方式传参 1.1.1         页面 参数需要解析成json对象:JSON.parse(JSON.stringify(query)) $.getJ ...

  8. JQuery 之 Ajax 异步和同步浅谈

    Ajax 同步和异步的区别 同步是当 JS 代码加载到当前 Ajax 的时候会把页面里所有的代码停止加载,页面出现假死状态:当这个 Ajax 执行完毕后才会继续运行其他代码此时页面假死状态才会解除.反 ...

  9. serialize

    Jquery的serialize()方法用于将表单元素转换为查询字符串格式, Submit按钮及File选择元素是不能序列化的. $('input:button').click(function() ...

  10. jQuery 源码分析 8: 回头看jQuery的构造器(jQuery.fn,jQury.prototype,jQuery.fn.init.prototype的分析)

    在第一篇jQuery源码分析中,简单分析了jQuery对象的构造过程,里面提到了jQuery.fn.jQuery.prototype.jQuery.fn.init.prototype的关系. 从代码中 ...