欢迎访问~原文出处——博客园-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 配对 动态规划 逆序对的更多相关文章

  1. BZOJ1786: [Ahoi2008]Pair 配对/1831: [AHOI2008]逆序对

    这两道题是一样的. 可以发现,-1变成的数是单调不降. 记录下原有的逆序对个数. 预处理出每个点取每个值所产生的逆序对个数,然后dp转移. #include<cstring> #inclu ...

  2. bzoj1786: [Ahoi2008]Pair 配对&&1831: [AHOI2008]逆序对

    一个自以为很对的东西,我们往-1放的数肯定是不增的. 然后就预处理一下,假如i这个位置放j会多多少逆序对. DP一下,我的复杂度应该是O(n*m^2)的,然而你随便搞都能省掉一个m吧,我算了算好像可以 ...

  3. 【BZOJ1786】[Ahoi2008]Pair 配对 DP

    [BZOJ1786][Ahoi2008]Pair 配对 Description Input Output Sample Input 5 4 4 2 -1 -1 3 Sample Output 4 题解 ...

  4. 【BZOJ1786】[Ahoi2008]Pair 配对

    题解: 打表出奇迹 能发现所有ai一定是不减的 其实很好证明啊.. 考虑两个位置x y(y在x右边) x的最优值已经知道了 考虑y处 先让y=x,然后开始变化 因为x处已经是最优的了,所以如果减小,那 ...

  5. B1786 [Ahoi2008]Pair 配对 逆序对+dp

    这个题有点意思,一开始没想到用dp,没啥思路,后来看题解才恍然大悟:k才1~100,直接枚举每个-1点的k取值进行dp就行了.先预处理出来sz[i][j]  i左边的比j大的数,lz[i][j]  i ...

  6. 【BZOJ1831】[AHOI2008]逆序对(动态规划)

    [BZOJ1831][AHOI2008]逆序对(动态规划) 题面 BZOJ 洛谷 题解 显然填入的数拎出来是不降的. 那么就可以直接大力\(dp\). 设\(f[i][j]\)表示当前填到了\(i\) ...

  7. bzoj1831: [AHOI2008]逆序对(DP+双精bzoj1786)

    1831: [AHOI2008]逆序对 Description 小可可和小卡卡想到Y岛上旅游,但是他们不知道Y岛有多远.好在,他们找到一本古老的书,上面是这样说的: 下面是N个正整数,每个都在1~K之 ...

  8. 洛谷 P4280 bzoj1786 [AHOI2008]逆序对(dp)

    题面 luogu bzoj 题目大意: 给你一个长度为\(n\)的序列,元素都在\(1-k\)之间,有些是\(-1\),让你把\(-1\)也变成\(1-k\)之间的数,使得逆序对最多,求逆序对最少是多 ...

  9. [BZOJ1786][BZOJ1831]逆序对

    [BZOJ1786][BZOJ1831]逆序对 试题描述 输入 输出 输入示例 - - 输出示例 数据规模及约定 见“输入” 题解 首先这题有一个性质,即,填的数从左到右一定不降.证明不妨读者自己yy ...

随机推荐

  1. BZOJ3527 [Zjoi2014]力 【fft】

    题目 给出n个数qi,给出Fj的定义如下: 令Ei=Fi/qi,求Ei. 输入格式 第一行一个整数n. 接下来n行每行输入一个数,第i行表示qi. 输出格式 n行,第i行输出Ei.与标准答案误差不超过 ...

  2. android 简单的读写联系人

    一.读取联系人 (1).从raw_contact表读 contact_id (2).从data表中读取data1 (3).从mimetypes读取mimetype 1.AndroidManifest. ...

  3. Linux 设置最大链接

    最大连接数 ulimit -SHn # 最大文件句柄数,最大打开文件数(等同最大连接数) ulimit -a # 查看 /etc/security/limits.conf # 进程最大打开文件数 # ...

  4. http://blog.csdn.net/w_e_i_/article/details/70766035

    http://blog.csdn.net/w_e_i_/article/details/70766035

  5. Spring+SpringMVC+Mybatis整合(二)

    目录结构:

  6. 之手算KD-tree

    转自:https://zhuanlan.zhihu.com/p/27453420 本文来源于Machine Learning: Clustering & Retrieval | Courser ...

  7. 【Mysql sql inject】【入门篇】sqli-labs使用 part 4【18-20】

    这几关的注入点产生位置大多在HTTP头位置处 常见的HTTP注入点产生位置为[Referer].[X-Forwarded-For].[Cookie].[X-Real-IP].[Accept-Langu ...

  8. 【转】Zabbix 3.0 从入门到精通(zabbix使用详解)

    [转]Zabbix 3.0 从入门到精通(zabbix使用详解) 第1章 zabbix监控 1.1 为什么要监控 在需要的时刻,提前提醒我们服务器出问题了 当出问题之后,可以找到问题的根源   网站/ ...

  9. C# 清理消息管道的消息

    using System;using System.Collections.Generic;using System.Linq;using System.Messaging;using System. ...

  10. 出现“error LNK1169: 找到一个或多个多重定义的符号”的原因

    或许,有人真的会这样写程序吧...所以才会碰到如下哥们提出的问题. https://zhidao.baidu.com/question/131426210.html 出现这种问题的原因链接中的最佳答案 ...