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 ...
随机推荐
- Python 基础【第十篇】内置类型
一.integral 类型 Python提供了两种integral类型,即int(整数)与bool(布尔值). 1.1.整数 整数的相关运算符.函数.数据类型转换 1.1.1.整数的运算符 前面已经讲 ...
- PeopleReady--办公学习类App产品
PeopleReady是能使人(公司或组织里的员工)快速Ready(经验+知识)的学习系统.对员工的好处是:- 可以迅速Ready,尽快符合岗位要求,尽快有Performance,尽快对公司有价值,从 ...
- ###《Max-Margin Early Event Detectors》
Paper reading. #@author: gr #@date: 2014-03-11 #@email: forgerui@gmail.com Early Detection Abstract: ...
- Markdown 生成目录
<link rel="stylesheet" href="http://yandex.st/highlightjs/6.2/styles/googlecode.mi ...
- CodeForces 527B
Description Ford Prefect got a job as a web developer for a small company that makes towels. His cur ...
- 学习C++ Primer 的个人理解(二)
本身就一定基础的读者我想变量常量这些概念应该已经不是问题了.但是本章还是有几个重点,需要特别留意一下的: 1.初始化和赋值是不同的操作 2.任何非0值都是true 3.使用新标准列表初始化,在有丢失精 ...
- ubuntu lua安装
#解压 tar -xzvf lua5.2.2.tar.gz #进入lua5.2.2文件夹 cd lua5.2.2 #执行make sudo make linux #提示如下错误: #lua.c:67: ...
- 九度OJ 1351 数组中只出现一次的数字
题目地址:http://ac.jobdu.com/problem.php?pid=1351 题目描述: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 输 ...
- Weui 微信网站开发样式插件使用教程
微信的网页样式正式发布了,搜了一下,正式引入了乐学一百微信端的项目中. <div class="weui_grids"> <a href="javasc ...
- centos 安装php ide (eclipse + php 插件)
1.检查更新并安装eclipse yum check-update yum install eclipse*此时的 eclipse 已经安装好了,默认是在/usr/lib/下的,可以通过cd /u ...