杭电 HOJ 1394 Minimum Inversion Number 解题报告
让我们求的是最少的ai>aj数。看到题目是没啥思路。。。在网上搜了一下,有暴力的,有线段树的。
暴力的比较简洁,也很容易弄懂,代码如下:
#include <iostream> using namespace std; int s[5001]; int main() { int i,j,n,m,a; while(cin>>n) { for(m=i=0;i<n;i++) for(cin>>s[i],j=0;j<i;j++) if(s[j]>s[i]) m++; a=m; for(i=0;i<n;i++) if(a>(m=m+n-s[i]*2-1)) a=m; cout<<a<<endl; } }
然后线段树是我自己写的(看过大牛的思路后得到启示。。。)
在输入s[i]后,我们要比较所有先输入的比它大的数字的数量。用线段树保存并更新,查询会快很多。代码如下:
#include <iostream> using namespace std; int s[16384],p[5001]; int main() { int i,j,n,m,a,t,sta,sum,v; while(cin>>n) { m=0; memset(s,0,sizeof(s)); t=n-1; sta=0; while(t) { t>>=1; sta++; } sta=1<<sta; for(i=0;i<n;i++) { cin>>t; p[i]=t; t+=sta; v=t; while(v) { s[v]+=1; v>>=1; } sum=0; v=sta*2-1; if(t<v) { t++; for(;v!=t;t>>=1,v>>=1) if(t&1) sum-=s[t-1]; m+=sum+s[t]; } } a=m; for(i=0;i<n;i++) if(a>(m=m+n-p[i]*2-1)) a=m; cout<<a<<endl; } }
代码不怎么好看,见谅。刚接触线段树,用的不是很熟,不过还是很强大的。用了2分的思想,问题的复杂度就会降到logN级别。