NC19883. [AHOI2008]逆序对
描述
输入描述
第一行两个正整数N和K。
第二行N个整数,每个都是-1或是一个在1~K之间的数。
输出描述
一个正整数,即这些数字里最少的逆序对个数。
示例1
输入:
5 4 4 2 -1 -1 3
输出:
4
C++(clang++11) 解法, 执行用时: 8ms, 内存消耗: 3068K, 提交时间: 2021-02-14 11:05:07
#include<iostream> #include<cstdio> #include<cstring> #define N 10010 #define M 110 using namespace std; int f[N][M],a[N],p[N],n,m,ans,lc[N][M],rc[N][M],l,r,t; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); if(a[i]!=-1) { for(int j=a[i]+1;j<=m;j++) ans+=p[j]; p[a[i]]++; } else r++; } memset(p,0,sizeof(p)); for(int i=1;i<=n;i++) if(a[i]==-1) { l++; lc[l][0]=t; for(int j=1;j<=m;j++) lc[l][j]=lc[l][j-1]-p[j]; } else p[a[i]]++,t++; memset(p,0,sizeof(p)); t=0; for(int i=n;i>=1;i--) if(a[i]==-1) { rc[r][0]=0; for(int j=1;j<=m;j++) rc[r][j]=rc[r][j-1]+p[j-1]; r--; } else p[a[i]]++; for(int i=1;i<=l;i++) { for(int j=1;j<=m;j++) f[i][j]=f[i-1][m]+lc[i][j]+rc[i][j]; for(int j=2;j<=m;j++) f[i][j]=min(f[i][j],f[i][j-1]); } cout<<f[l][m]+ans; }