zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    UVA 1025 A Spy in the Metro DP水题
    ZOJ 3814 Sawtooth Puzzle BFS
    ZOJ 3816 Generalized Palindromic Number
    UVA 10859 Placing Lampposts 树形DP
    UVA 11825 Hackers' Crackdown 状压DP
    POJ 2887 Big String 线段树 离线处理
    POJ 1635 Subway tree systems Hash法判断有根树是否同构
    BZOJ 3110 k大数查询 & 树套树
    sdoi 2009 & 状态压缩
    来自于2016.2.24的flag
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1786.html
Copyright © 2011-2022 走看看