bzoj1786

来源:互联网 发布:守望先锋数据战766 编辑:程序博客网 时间:2024/06/07 07:21

显然填的数是不降的。。。

然后把-1都扣出来,f[i][j]表示前i个-1填j的逆序数


然后分别对与每个点求出来他前面的比他大的和后面的比他小的数就可以了

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#define MAX 10009#define rep(i,j,k) for(int i=j;i<=k;i++)#define inf 0x7fffffff/2using namespace std;int n,a[MAX],p[MAX];int k,t,big[MAX][101],small[MAX][101],f[MAX][101];int main(){scanf("%d%d",&n,&k);t=0;rep(i,1,n){scanf("%d",&a[i]);if(a[i]==-1)p[++t]=i;}rep(i,2,n)rep(j,1,k){big[i][j]=big[i-1][j];if(a[i-1]>j)big[i][j]++;}for(int i=n-1;i>=1;i--)rep(j,1,k){small[i][j]=small[i+1][j];if(a[i+1]!=-1&&a[i+1]<j)small[i][j]++;}memset(f,63,sizeof(f));f[0][0]=0;rep(i,1,k)f[1][i]=big[p[1]][i]+small[p[1]][i];rep(i,2,t)rep(j,1,k)rep(w,1,j)f[i][j]=min(f[i][j],f[i-1][w]+big[p[i]][j]+small[p[i]][j]);int ans=inf;rep(i,1,k)ans=min(ans,f[t][i]);ans=((ans==f[n+1][k+1])?0:ans);rep(i,1,n)ans+=big[i][a[i]];printf("%d\n",ans);return 0;}

0 0