1. 程式人生 > >bzoj1786: [Ahoi2008]Pair 配對&&1831: [AHOI2008]逆序對

bzoj1786: [Ahoi2008]Pair 配對&&1831: [AHOI2008]逆序對

int void 求逆序對 ini lse -i cstring change ace

一個自以為很對的東西,我們往-1放的數肯定是不增的。

然後就預處理一下,假如i這個位置放j會多多少逆序對。

DP一下,我的復雜度應該是O(n*m^2)的,然而你隨便搞都能省掉一個m吧,我算了算好像可以過就不管了。

註意樹狀數組的時候getsum是a[i]-1,相同是不算逆序對的

#include<cstdio> 
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using
namespace std; int s[110]; int lowbit(int x){return x&-x;} void change(int x,int k) { while(x<=100) { s[x]+=k; x+=lowbit(x); } } int getsum(int x) { int ret=0; while(x>0) { ret+=s[x]; x-=lowbit(x); } return ret; }
//-----------bit-求逆序對------------------- int a[11000]; int c[11000][110]; int f[11000][110]; int main() { int n,m; scanf("%d%d",&n,&m); int _know=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); if(a[i]!=-1) _know++, change(a[i],1);
else for(int j=1;j<=m;j++)c[i][j]=_know-getsum(j); } memset(s,0,sizeof(s)); int ans=0; for(int i=n;i>=1;i--) { if(a[i]!=-1) { ans+=getsum(a[i]-1); change(a[i],1); } else for(int j=1;j<=m;j++)c[i][j]+=getsum(j-1); } //--------init------------- memset(f,63,sizeof(f));f[1][1]=0; for(int i=2;i<=n;i++) { for(int j=1;j<=m;j++) { if(a[i]!=-1) { f[i][j]=f[i-1][j]; } else { for(int k=1;k<=j;k++) f[i][j]=min(f[i][j],f[i-1][k]+c[i][j]); } } } int ss=(1<<30); for(int j=1;j<=m;j++)ss=min(ss,f[n][j]); printf("%d\n",ans+ss); return 0; }

bzoj1786: [Ahoi2008]Pair 配對&&1831: [AHOI2008]逆序對