标签:树状数组
Description
Input
Output
Sample Input
5 9 1 0 5 4 3 1 2 3 0
Sample Output
6 0
解题思路:
题目大意是给一个数列,相邻两个进行交换,使之按从小到大排序,问最少交换几次。该题和之前的做的Janan是一个类型的,都是求逆序对。唯一难点就是数据特别大,数列中的元素值可以达到999999999,树状数组不可能开这么大。但由于数列最多有500000个数,所以可以进行离散化处理,把数列中的元素压缩到1-500000之间。离散化就是将输入的值与下标相对应,可以用结构体实现,然后对输入的值进行从小到大排序,再用一个数组去存储其下标的值。答案会超int范围,得用Int64存储。
AC代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn = 500005; __int64 c[maxn]; struct node { int a, b; // a存储输入的值,b存储其坐标 }p[maxn]; bool cmp(node v, node s) { return v.a < s.a; } int lowbit(int a) { return a & (-a); } void Update(int a) { while(a < maxn) { c[a] += 1; a += lowbit(a); } } __int64 Sum(int a) { __int64 sum = 0; while(a > 0) { sum += c[a]; a -= lowbit(a); } return sum; } int main() { int n, a[maxn]; __int64 ans; while(scanf("%d", &n) && n) { ans = 0; memset(c, 0, sizeof(c)); for(int i = 1; i <= n; i++) { scanf("%d", &p[i].a); p[i].b = i; } sort(p + 1, p + n + 1, cmp); for(int i = 1; i <= n; i++) // 离散化处理 a[p[i].b] = i; for(int i = 1; i <= n; i++) { ans += i - Sum(a[i]) - 1; // 要-1,因为算的是输入该值之前的元素个数 Update(a[i]); } printf("%I64d\n", ans); } return 0; }
Ultra-QuickSort(树状数组 + 离散化),布布扣,bubuko.com
标签:树状数组
原文地址:http://blog.csdn.net/userluoxuan/article/details/38294563