http://poj.org/problem?id=2299
坑:答案是long long 输出……!!!!!
题意是:求一个数组进行冒泡排序交换的次数
题解:求逆序数
题解Ⅰ:
归并排序求逆序数
归并排序求逆序数之前写过
1.归并排序是把两个有序的数组合并成为一个有序的数组,利用分治的思想就可以进行排序
逆序数可以利用这个思想求
求出第一个数组的逆序数,和第二个数组的逆序数,再将两个数组整体的逆序数求出来
f(x,y) = f(x,mid) + f(mid,y) + 之后数组的逆序数
#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <cstdlib> #include <vector> #include <map> #include <queue> #include <stack> const int MAXN = 500000 + 10; const int INF = 0x7fffffff; const int MOD = 1000007; const double ESP = 10e-8; const double Pi = acos(-1.0); typedef long long LL; using namespace std; LL a[MAXN]; LL b[MAXN]; LL h(int s,int e){ if(e-s <= 1){ return 0; } int mid = s + (e-s)/2; LL x = h(s,mid); LL y = h(mid,e); int p1 = s; int p2 = mid; int p3 = s; LL cnt = 0; while(p1 < mid || p2 < e){ if(p2 >= e || (p1 < mid && a[p1] < a[p2])){ b[p3++] = a[p1++]; } else{ b[p3++] = a[p2++]; cnt += (mid-p1); /*第二个数组当前元素比第一个数组当前元素小,所以第一个数组从当前元素到最后的元素都比第二个数组的大(数组一,二都已经有序了),所以第一个数组结尾下标,减去第一个数组的当前元素就是两个数组的逆序数*/ } } for(int i = s;i < e;i++){ a[i] = b[i]; } return x+y+cnt; } int main(){ //freopen("input.txt","r",stdin); int n; while(~scanf("%d",&n) && n){ for(int i = 0;i < n;i++){ scanf("%d",&a[i]); } LL ans = h(0,n); printf("%lld\n",ans); } return 0; }
题解Ⅱ:
http://www.cnblogs.com/shenshuyang/archive/2012/07/14/2591859.html
这个童鞋写得已经很棒了
1.数组元素太大,而n 的个数又很少,所以需要离散化
离散化:
用struct Node{
int v;
int order;
};
将元素读入,并且将元素的次序读入
将元素排序之后,下标的标号一定程度上是代表元素的大小
所以用下标的标号就可以表示元素
这样范围就减少了
2.
树状数组是求 前 i 个 元素的和
先 add(a[i],1)
再 i - sum(a[i])
前面已经有 i 个元素了,sum(a[i]) 表示 1 - a[i] 的和 ,而 i - sum(a[i]) 表示有多少个数字比 a[i] 大 但是 次序却在 i 位置的前面 就是 a[i] 元素的逆序数
#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <cstdlib> #include <vector> #include <map> #include <queue> #include <stack> const int MAXN = 500000 + 10; const int INF = 0x7fffffff; const int MOD = 1000007; const double ESP = 10e-8; const double Pi = acos(-1.0); typedef long long LL; using namespace std; int a[MAXN]; int bit[MAXN+1]; int n; struct Node{ int v; int order; bool operator < (const Node x)const{ return v < x.v; } }; Node in[MAXN]; int sum(int i){ int s = 0; while(i>0){ s += bit[i]; i -= (i & -i); } return s; } void add(int i,int x){ while(i <= n){ bit[i] += x; i += (i&-i); } } int main(){ // freopen("input.txt","r",stdin); while(~scanf("%d",&n) && n){ memset(bit,0,sizeof(bit)); for(int i = 1;i <= n;i++){ scanf("%d",&in[i].v); in[i].order = i; } sort(in+1,in+1+n); for(int i = 1;i <= n;i++){ a[in[i].order] = i; } LL ans = 0; for(int i = 1;i <= n;i++){ add(a[i],1); ans += i-sum(a[i]); } printf("%lld\n",ans); } return 0; }
时间: 2024-10-03 07:17:14