hdu1394 Minimum Inversion Number(树状数组求逆序数)
2016-02-15 16:26
633 查看
题目大意:给出一个数列,然后让这个数列滚动,求每种数列的逆序数,输出其中的最小值。
做法:用树状数组可做,把原数列由大到小加入树状数组,统计在这个数前面的已加入数的个数,求和,即为原数列的逆序数。数列滚动时,把第一个数字以至最后,那么,鑫逆序数为:原逆序数 - 数列中比它小的数字个数 + 数列中比它大的数字个数,最后可得方程 sum=sum-2*a[1]+n-1 ;
以下是代码:
做法:用树状数组可做,把原数列由大到小加入树状数组,统计在这个数前面的已加入数的个数,求和,即为原数列的逆序数。数列滚动时,把第一个数字以至最后,那么,鑫逆序数为:原逆序数 - 数列中比它小的数字个数 + 数列中比它大的数字个数,最后可得方程 sum=sum-2*a[1]+n-1 ;
以下是代码:
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; int c[5050],n,b[5050]; struct anode { int num,v; }a[5050]; bool cmp(anode x,anode y) { return x.v>y.v; } int lowbit(int x) { return x&-x; } void add(int x) { while(x<=n){ c[x]+=1; x+=lowbit(x); } } int sum(int x) { int ret=0; while(x>0){ ret+=c[x]; x-=lowbit(x); } return ret; } int main() { freopen("in.txt","r",stdin); while(scanf("%d",&n)!=EOF){ memset(c,0,sizeof(c)); memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); for(int i=1;i<=n;i++){ scanf("%d",&a[i].v); b[i]=a[i].v;//记录原数列。 a[i].v++; //用注意树状数组可用下标不包含0。 a[i].num=i; //记录原数列数字的的位置。 } sort(a+1,a+n+1,cmp); int temp=0; for(int i=1;i<=n;i++){ add(a[i].num); temp+=sum(a[i].num)-1; } int ans=temp; for(int i=1;i<n;i++){ temp=temp-2*b[i]+n-1; ans=min(temp,ans); } printf("%d\n",ans); } return 0; }
相关文章推荐
- JavaScript跨域总结与解决办法
- lighttpd-1.4.39 : plugin
- xcode 在run时 显示 Build succeeded 但是程序无法应
- python笔记--廖雪峰站学习笔记
- ActiveX控件通过IE安装问题
- yz2
- spring security 3中的10个典型用法小结
- [翻译]HBase 中的 ACID
- 解决一次由于SSL证书到期导致的网站不能访问的问题(Nginx,php,Apache)
- C# WebService (二)发布与IIS配置
- [BZOJ]3223文艺平衡树做题笔记
- Android应用程序权限机制的源代码分析(2)
- Android中保存网络图片到SD卡
- myaudio.duration为null的解决办法
- 删除嵌套表类型列的元素值
- POJ3686 KM最大权匹配+高难度建图
- js基础篇——call/apply、arguments、undefined/null
- 2016.2.15 16年第一天上班 ZooKeeper集群的安装、配置
- Android应用程序权限机制的源代码分析(1)
- 重写前奏~继承和多态