bzoj1831 逆序对 (dp+树状数组)
注意到,所有的-1应该是一个不降的序列,否则不会更优
那就先求出来不是-1的的逆序对个数,然后设f[i][j]表示第i个-1放成j的前i个-1带来的最小逆序对数量
这个可以树状数组来求
1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define CLR(a,x) memset(a,x,sizeof(a)) 4 using namespace std; 5 typedef long long ll; 6 const int maxn=1e4+10,maxk=110; 7 8 inline ll rd(){ 9 ll x=0;char c=getchar();int neg=1; 10 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 11 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 12 return x*neg; 13 } 14 15 16 int f[maxn][maxk],tr[maxn],a[maxn],b[maxn],N,K,M; 17 18 inline int lowbit(int x){return x&(-x);} 19 inline void add(int x,int y){ 20 for(;x<=K;x+=lowbit(x)) tr[x]+=y; 21 } 22 inline int query(int x){ 23 int re=0;for(;x;x-=lowbit(x)) re+=tr[x];return re; 24 } 25 26 int main(){ 27 //freopen("","r",stdin); 28 int i,j,k; 29 N=rd(),M=0,K=rd(); 30 int ans=0; 31 for(i=1;i<=N;i++){ 32 a[i]=rd(); 33 if(a[i]==-1) b[++M]=i; 34 else{ 35 ans+=query(K)-query(a[i]); 36 add(a[i],1); 37 } 38 } 39 CLR(tr,0); 40 for(i=1,j=1;i<=M;i++){ 41 for(;j<=b[i];j++){ 42 if(a[j]!=-1) add(a[j],1); 43 } 44 for(k=1;k<=K;k++) 45 f[i][k]+=query(K)-query(k); 46 } 47 CLR(tr,0); 48 for(i=M,j=N;i;i--){ 49 for(;j>=b[i];j--){ 50 if(a[j]!=-1) add(a[j],1); 51 } 52 for(k=1;k<=K;k++) 53 f[i][k]+=query(k-1); 54 } 55 for(i=1;i<=M+1;i++){ 56 for(j=1;j<=K;j++){ 57 int mi=1e9; 58 for(k=1;k<=j;k++){ 59 mi=min(mi,f[i-1][k]); 60 } 61 f[i][j]+=mi; 62 } 63 } 64 printf("%d\n",f[M+1][K]+ans); 65 return 0; 66 }