zoukankan      html  css  js  c++  java
  • 【BZOJ1831】[AHOI2008]逆序对(动态规划)

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

    题面

    BZOJ
    洛谷

    题解

    显然填入的数拎出来是不降的。
    那么就可以直接大力(dp)
    (f[i][j])表示当前填到了(i),上一个填的数是(j)的最小逆序对数。
    随便拿什么维护一下转移就好了。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define MAX 10010
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int n,K,sum,a[MAX],ans=1e9,f[MAX][101],s1[101],s2[101];
    int main()
    {
    	n=read();K=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	for(int i=1;i<=n;++i)if(~a[i])s2[a[i]]+=1;
    	for(int i=1;i<=K;++i)s2[i]+=s2[i-1];
    	for(int i=1;i<=K;++i)s1[i]=s2[i];
    	for(int i=1;i<=n;++i)
    		if(~a[i])
    		{
    			sum+=s1[a[i]-1];
    			for(int j=a[i];j<=K;++j)s1[j]-=1;
    		}
    	for(int i=1;i<=n;++i)
    		if(~a[i])
    		{
    			for(int j=1;j<=K;++j)f[i][j]=f[i-1][j];
    			for(int j=a[i];j<=K;++j)s2[j]-=1,s1[j]+=1;
    		}
    		else
    		{
    			for(int j=1;j<=K;++j)f[i][j]=f[i-1][j]+s2[j-1]+s1[K]-s1[j];
    			for(int j=1;j<K;++j)f[i][j+1]=min(f[i][j+1],f[i-1][j]+s2[j]+s1[K]-s1[j+1]);
    			for(int j=2;j<=K;++j)f[i][j]=min(f[i][j],f[i][j-1]);
    		}
    	for(int i=1;i<=K;++i)ans=min(ans,f[n][i]);
    	printf("%d
    ",ans+sum);
    	return 0;
    }
    
  • 相关阅读:
    Android开发——Activity启动模式详解
    Spring核心技术(十一)——基于Java的容器配置(一)
    【数学】控制论
    【Mongo】聚合函数
    【Deeplearning】blog
    【Python】添加注册表信息脚本
    【数据库】备份与恢复
    【MongoDB】数组长度查询
    【Mysql】修改最大连接数
    【Python】多线程2
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10486547.html
Copyright © 2011-2022 走看看