欢迎访问~原文出处——博客园-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. IntelliJ IDEA AndroidStudio SVN无法使用

    1.Cann't Run Program "SVN" 把勾都去掉,结果没有任何反应.2.重新安装TotoriseSVN,设置Svn.exe路径,主要不要勾选Enable Inter ...

  2. 20155220 2016-2017-2 《Java程序设计》第七周学习总结

    20155220 2016-2017-2 <Java程序设计>第七周学习总结 教材学习内容总结 Lambda 如果使用JDK8的话,可以使用Lambda特性去除重复的信息. 在只有Lamb ...

  3. 20155333 2016-2017-2 《Java程序设计》第六周学习总结

    20155333 2016-2017-2 <Java程序设计>第六周学习总结 教材学习内容总结 流(Stream)是对「输入输出」的抽象,注意「输入输出」是相对程序而言的 InputStr ...

  4. 不同数据库下的web.config中数据库连接字符串

    <connectionStrings> <add name="OADBConnectionString" connectionString="Data ...

  5. elasticsearch 单机多实例

    elasticsearch 配置单机器多实例 host: - - path data: /opt/elasticsearch/data/node1 /opt/elasticsearch/data/no ...

  6. 理解django框架中的MTV与MVC模式

    1.Models:一个抽象层,用来构建和操作你的web应用中的数据,模型是你的数据的唯一的.权威的信息源.它包含你所储存数据的必要字段和行为.通常,每个模型对应数据库中唯一的一张表. from dja ...

  7. POJ1113 Wall【凸包】

    题意: 求把城堡围起来需要的最小墙壁周长. 思路: 围墙周长为=n条平行于凸包的线段+n条圆弧的长度=凸包周长+围墙离城堡距离L为半径的圆周长. 代码: ...还是看大佬写的,自己做个记录方便日后复习 ...

  8. HDU4635 Strongly connected【强连通】

    题意: 给一个n个点的简单有向图,问最多能加多少条边使得该图仍然是简单有向图,且不是强连通图.简单有向图的定义为:没有重边,无自环. 强连通图的定义为:整个图缩点后就只有一个点,里面包含n个原点,也就 ...

  9. 第16月第25天 tableView设置UITableViewStyleGrouped顶部有空余高度

    1. 正确的处理方法 1)设置标头的高度为特小值 (不能为零 为零的话苹果会取默认值就无法消除头部间距了) UIView *view = [[UIView alloc]initWithFrame:CG ...

  10. android的五个进程优先级,内存不足时被清理的顺序

    Android操作系统尝试尽可能长时间的保持应用的进程,但当可用内存很低时最终要移走一部分进程.怎样确定那些程序可以运行,那些要被销毁,Android让每一个进程在一个重要级的基础上运行,重要级低的进 ...