[树状数组求逆序对]光荣的梦想
2017-10-12 19:37
155 查看
题目描述:
Prince对他在这片大陆上维护的秩序感到满意,于是决定启程离开艾泽拉斯。在他动身之前,Prince决定赋予King_Bette最强大的能量以守护世界、保卫这里的平衡与和谐。在那个时代,平衡是个梦想。因为有很多奇异的物种拥有各种不稳定的能量,平衡瞬间即被打破。KB决定求助于你,帮助他完成这个梦想。
一串数列即表示一个世界的状态。
平衡是指这串数列以升序排列,而从一串无序数列到有序数列需要通过交换数列中的元素来实现。KB的能量只能交换相邻两个数字。他想知道他最少需要交换几次就能使数列有序。
输入格式:
第一行为数列中数的个数 N(n≤100000)。
第二行为 N 个数 a1~an (每个数小于100000),表示当前数列的状态。
输出格式:
输出一个整数,表示最少需要交换几次能达到平衡状态。
样例输入:
4
2 1 4 3
样例输出:
2
备注:
本题另外一种描述:给定一个序列 a1,a2,…,an,如果存在i<j 并且ai>aj ,那么我们称之为逆序对,求逆序对的数目。
题目分析:
求逆序对有多种方法,如归并排序。这里介绍树状数组求逆序对的方法。对于一个原来的序列,假设一个数a[i],如果它前面有m个比它大的,那么对于a[i]就有m个逆序对。对于每个数都是这样。所以我们可以用树状数组维护比它小的有多少个,按顺序加入,sum[i],i代表此数的大小,sum记录个数。加入后又查询就可以得到前面比它小的有多少个。减一下就是比它大的有几个。
下附代码,之所以排序,相当于是在离散化,将原来的直接的数据大小,转成是第几大,就可以处理数据值较大和有负数的情况,而大小关系是不变的。
附代码:
Prince对他在这片大陆上维护的秩序感到满意,于是决定启程离开艾泽拉斯。在他动身之前,Prince决定赋予King_Bette最强大的能量以守护世界、保卫这里的平衡与和谐。在那个时代,平衡是个梦想。因为有很多奇异的物种拥有各种不稳定的能量,平衡瞬间即被打破。KB决定求助于你,帮助他完成这个梦想。
一串数列即表示一个世界的状态。
平衡是指这串数列以升序排列,而从一串无序数列到有序数列需要通过交换数列中的元素来实现。KB的能量只能交换相邻两个数字。他想知道他最少需要交换几次就能使数列有序。
输入格式:
第一行为数列中数的个数 N(n≤100000)。
第二行为 N 个数 a1~an (每个数小于100000),表示当前数列的状态。
输出格式:
输出一个整数,表示最少需要交换几次能达到平衡状态。
样例输入:
4
2 1 4 3
样例输出:
2
备注:
本题另外一种描述:给定一个序列 a1,a2,…,an,如果存在i<j 并且ai>aj ,那么我们称之为逆序对,求逆序对的数目。
题目分析:
求逆序对有多种方法,如归并排序。这里介绍树状数组求逆序对的方法。对于一个原来的序列,假设一个数a[i],如果它前面有m个比它大的,那么对于a[i]就有m个逆序对。对于每个数都是这样。所以我们可以用树状数组维护比它小的有多少个,按顺序加入,sum[i],i代表此数的大小,sum记录个数。加入后又查询就可以得到前面比它小的有多少个。减一下就是比它大的有几个。
下附代码,之所以排序,相当于是在离散化,将原来的直接的数据大小,转成是第几大,就可以处理数据值较大和有负数的情况,而大小关系是不变的。
附代码:
#include<iostream> #include<cstring> #include<string> #include<cstdlib> #include<cstdio> #include<ctime> #include<cmath> #include<cctype> #include<iomanip> #include<algorithm> using namespace std; const int N=1e5+10; int n,sum ,num ; long long ans; struct node{ int w; int po; }a ; bool comp(const node &a,const node &b) { if(a.w!=b.w) return a.w<b.w; return a.po<b.po; } int lowbit(int i) { return i&(-i); } void insert(int x) { for(int i=x;i<=n;i+=lowbit(i)) sum[i]++; } int query(int x) { int ret=0; for(int i=x;i>=1;i-=lowbit(i)) ret+=sum[i]; return ret; } int main() { //freopen("lx.in","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i].w); a[i].po=i; } sort(a+1,a+n+1,comp); for(int i=1;i<=n;i++) num[a[i].po]=i; for(int i=1;i<=n;i++) { insert(num[i]); ans+=i-query(num[i]); } printf("%I64d",ans); return 0; }
相关文章推荐
- [复习]树状数组求逆序对 光荣的梦想
- 光荣的梦想 (树状数组求逆序数和)
- nyoj 117 求逆序数【线段树 树状数组 归并排序】
- HDU - 4911 - Inversion(树状数组逆序数+离散化)
- POJ 2299 离散化+树状数组求逆序数
- 树状数组与逆序对数
- 线段树或树状数组求逆序数
- 2789: [Poi2012]Letters (树状数组求逆序对数)
- hdu 5193 分块 树状数组 逆序对
- 光荣的梦想(逆序对模板)
- POJ:2299 Ultra-QuickSort(树状数组+离散化+技巧+求逆序对)
- 树状数组求逆序数
- 树状数组求逆序数
- 树状数组求逆序对
- HDOJ 题目3465 Life is a Line(树状数组求逆序对)
- 【bzoj3295】 CQOI2011动态逆序对 树状数组+主席树
- 树状数组求逆序数
- 树状数组求逆序数 模版
- pku 3067 Japan 树状数组求逆序数
- bzoj3289 树状数组加莫队注意这题每天的交换该是不影响的。。。还有一次交换等价于去掉一个逆序