POJ 2299 解题报告

来源:互联网 发布:淘宝虚拟物品记录 编辑:程序博客网 时间:2024/06/05 11:29

这道题我是按照mergecnt做的,即原题等同于求数组中的inversion count(前面的数比后面的数大的pair的个数)。然后在merge sort中统计一下这样的对有多少个就可以。时间复杂度和merge sort一样,都是O(nlogn)。

geeksforgeeks上面有很好的解释和实现:http://www.geeksforgeeks.org/counting-inversions/

最终结果要用long long表示,因为逆对数的范围是n^2,即50w * 50w = 2.5 * 10^9,没有意识到这一点贡献了一次WA。

discuss和网上都有用线段树求逆对数的,方法很巧妙,需要首先离散化:http://www.cnblogs.com/frog112111/p/3268632.html

2299Accepted3744K1282MSC++1350B

/* ID: thestor1 LANG: C++ TASK: poj2299 */#include <iostream>#include <fstream>#include <cmath>#include <cstdio>#include <cstring>#include <limits>#include <string>#include <vector>#include <list>#include <set>#include <map>#include <queue>#include <stack>#include <algorithm>#include <cassert>using namespace std;const int MAXN = 500000;// const int MAXN = 10;int nums[MAXN];int tmp[MAXN];void mergecnt(int left, int right, long long &cnt){if (left >= right){return;}int mid = left + (right - left) / 2;mergecnt(left, mid, cnt);mergecnt(mid + 1, right, cnt);int i, j, k = left;for (i = left, j = mid + 1; i <= mid && j <= right;){if (nums[i] <= nums[j]){tmp[k] = nums[i];i++;k++;}else{// nums[i] > nums[j]cnt += mid - i + 1;tmp[k] = nums[j];j++;k++;}}while (i <= mid){// cnt += mid - i + 1;tmp[k] = nums[i];i++;k++;}while (j <= right){tmp[k] = nums[j];j++;k++;}for (i = left; i <= right; ++i){nums[i] = tmp[i];}}int main(){int N;while (cin >> N && N){for (int i = 0; i < N; ++i){cin >> nums[i];}long long cnt = 0;mergecnt(0, N - 1, cnt);cout << cnt << endl;}return 0;  }


0 0
原创粉丝点击