BZOJ1786 [Ahoi2008]Pair 配对 动态规划 逆序对
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ1786
题意概括
给出长度为n的数列,只会出现1~k这些正整数。现在有些数写成了-1,这些-1可以变成任何数。
求把这些-1变成1~k中的正整数之后,最少的逆序对个数为多少。
题解
我们可以判断,这些-1中写的数字一定是单调不降的。
为什么?我们把答案序列的所有-1位抽出来,如果答案序列中有一组是逆序的,那么交换他们,一定可以保证小的那个换到大的那个的位置的时候,它左右产生的逆序对数一定比大的原先不多,同理,大的在原先的小的的位置上,产生的逆序对数也比原来小的不多。交换他们,本身就会减少一个逆序对,那么一定是更优的。
所以我们确定了一定是单调不降的。
那么这些-1位之间也不会有逆序对。
那么就是一个简单的dp了。
设dp[i][j]表示前i位,填到了j这个数,最少的逆序对数。注意这里的逆序对数是指-1中的数添入之后产生的逆序对数。
然后取一个最小值,作为所有-1位产生的最少逆序对数。
然后加上原来有的数产生的逆序对数就可以了。
代码
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=10000+5,M=100+5;
int n,m,a[N],sml[N][M],big[N][M],tot[N][M],rot[N][M],dp[N][M];
int main(){
scanf("%d%d",&n,&m);
memset(tot,0,sizeof tot);
memset(rot,0,sizeof rot);
memset(sml,0,sizeof sml);
memset(big,0,sizeof big);
memset(dp,0,sizeof dp);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
for (int j=1;j<=m;j++)
tot[i][j]=tot[i-1][j];
if (a[i]!=-1)
tot[i][a[i]]++;
for (int j=m;j>=1;j--)
big[i][j]=big[i][j+1]+tot[i][j];
}
for (int i=n;i>=1;i--){
for (int j=1;j<=m;j++)
rot[i][j]=rot[i+1][j];
if (a[i]!=-1)
rot[i][a[i]]++;
for (int j=1;j<=m;j++)
sml[i][j]=sml[i][j-1]+rot[i][j];
}
int tot=0;
for (int i=1;i<=n;i++){
int Min=1<<28;
if (a[i]!=-1)
tot+=big[i-1][a[i]+1]+sml[i+1][a[i]-1];
for (int j=1;j<=m;j++){
if (a[i]!=-1){
dp[i][j]=dp[i-1][j];
continue;
}
Min=min(Min,dp[i-1][j]);
dp[i][j]=Min+big[i-1][j+1]+sml[i+1][j-1];
}
}
int ans=1<<28;
for (int i=1;i<=m;i++)
ans=min(ans,dp[n][i]);
printf("%d",ans+tot/2);
return 0;
}
BZOJ1786 [Ahoi2008]Pair 配对 动态规划 逆序对的更多相关文章
- BZOJ1786: [Ahoi2008]Pair 配对/1831: [AHOI2008]逆序对
这两道题是一样的. 可以发现,-1变成的数是单调不降. 记录下原有的逆序对个数. 预处理出每个点取每个值所产生的逆序对个数,然后dp转移. #include<cstring> #inclu ...
- bzoj1786: [Ahoi2008]Pair 配对&&1831: [AHOI2008]逆序对
一个自以为很对的东西,我们往-1放的数肯定是不增的. 然后就预处理一下,假如i这个位置放j会多多少逆序对. DP一下,我的复杂度应该是O(n*m^2)的,然而你随便搞都能省掉一个m吧,我算了算好像可以 ...
- 【BZOJ1786】[Ahoi2008]Pair 配对 DP
[BZOJ1786][Ahoi2008]Pair 配对 Description Input Output Sample Input 5 4 4 2 -1 -1 3 Sample Output 4 题解 ...
- 【BZOJ1786】[Ahoi2008]Pair 配对
题解: 打表出奇迹 能发现所有ai一定是不减的 其实很好证明啊.. 考虑两个位置x y(y在x右边) x的最优值已经知道了 考虑y处 先让y=x,然后开始变化 因为x处已经是最优的了,所以如果减小,那 ...
- B1786 [Ahoi2008]Pair 配对 逆序对+dp
这个题有点意思,一开始没想到用dp,没啥思路,后来看题解才恍然大悟:k才1~100,直接枚举每个-1点的k取值进行dp就行了.先预处理出来sz[i][j] i左边的比j大的数,lz[i][j] i ...
- 【BZOJ1831】[AHOI2008]逆序对(动态规划)
[BZOJ1831][AHOI2008]逆序对(动态规划) 题面 BZOJ 洛谷 题解 显然填入的数拎出来是不降的. 那么就可以直接大力\(dp\). 设\(f[i][j]\)表示当前填到了\(i\) ...
- bzoj1831: [AHOI2008]逆序对(DP+双精bzoj1786)
1831: [AHOI2008]逆序对 Description 小可可和小卡卡想到Y岛上旅游,但是他们不知道Y岛有多远.好在,他们找到一本古老的书,上面是这样说的: 下面是N个正整数,每个都在1~K之 ...
- 洛谷 P4280 bzoj1786 [AHOI2008]逆序对(dp)
题面 luogu bzoj 题目大意: 给你一个长度为\(n\)的序列,元素都在\(1-k\)之间,有些是\(-1\),让你把\(-1\)也变成\(1-k\)之间的数,使得逆序对最多,求逆序对最少是多 ...
- [BZOJ1786][BZOJ1831]逆序对
[BZOJ1786][BZOJ1831]逆序对 试题描述 输入 输出 输入示例 - - 输出示例 数据规模及约定 见“输入” 题解 首先这题有一个性质,即,填的数从左到右一定不降.证明不妨读者自己yy ...
随机推荐
- 如何理解<base href="<%=basePath%>"
原文链接http://316325524.blog.163.com/blog/static/6652052320111118111620897/ "base href " 今天在写 ...
- Linux cache 缓存过大
linux cache 缓存过大 : 除重启服务 之外:直接释放内存方式之一: 修改配置释放cached内存: echo > /proc/sys/vm/drop_caches
- luogu P2662 牛场围栏
传送门 因为一个木板可以切掉最多\(m\),所以可以先预处理哪些长度的木板可用,开个桶,然后对\([l-m,l]\)打标记,再把打了标记的数取出来 假设可用长度\(a_1,a_2,,,a_n\)从小到 ...
- logback配置按天产生日志文件
1 依赖Jar包 pom配置 也可以根据自己的版本来 <dependency> <groupId>org.slf4j</groupId> <artifactI ...
- webstorm11.0.3连接ftp
一.工具 webstorm11.0.3 ftp工具:Beyond Compare 3 二.步骤 1.打开项目工程,按照下图中路径,打开ftp配置界面 2.在ftp配置界面 (1)右上角+号新建配置,选 ...
- 访问tp3.2的项目时出现No input file specified.的解决办法
解决办法很简单如下: 打开.htaccess 在RewriteRule 后面的index.php教程后面添加一个“?” 原来的代码如下 <IfModule mod_rewrite.c> O ...
- haar特征(转)
转载链接:http://blog.csdn.net/lanxuecc/article/details/52222369 Haar特征 Haar特征原理综述 Haar特征是一种反映图像的灰度变化的,像素 ...
- eclipse删除多余的工作空间
window->preferences->startup and shutdown->workspaces如图:
- 012_如何清除DNS缓存
运维过程中经常会进行切换域名解析等的操作,就需要查看是否更新.但常常DNS设置已经更新了,但是用户那边的DNS还是没有更新. 以下分析几点原因及我的解决方案. 一. <1>本地你的dns缓 ...
- GO-time.after 用法
初学GO,time包里sleep是最常用,今天突然看到一个time.after,特记录time.after用法笔记如下: 首先是time包里的定义 // After waits for the dur ...