POJ2299 Ultra-QuickSort 归并排序和逆序数,树状数组
来源:互联网 发布:安卓改iphone6在线软件 编辑:程序博客网 时间:2024/04/30 09:48
题意是要求排序交换的次数,因为数据较大,冒泡肯定超时,快排又没办法得到交换次数,所以用复杂度相同的归并排序,这里有一个逆序对的概念:
对于一个包含N个非负整数的数组A[1..n],如果i < j,且A[ i ]>A[ j ],则称(A[ i] ,A[ j] )为数组A中的一个逆序对。例如,数组(3,1,4,5,2)的逆序对有(3,1),(3,2),(4,2),(5,2),共4个
要求交换次数,也就是求逆序对的个数。
注意这里因为数据较大,要用__int64定义num(两条下划线)
代码如下:
#include<stdio.h>#include<stdlib.h>__int64 num; //这里要用__Int64(注意是两条下划线)int a[1000000], b[1000000];void fix(int *a,int*b,int left,int mid,int right){ //合并函数 int i = left; int j = mid+1; int k = left; while (i < mid+1&&j<right+1)//这里都是+1,mid和right都可以取到 { if (a[i] <= a[j]) b[k++] = a[i++]; else { b[k++] = a[j++]; num += mid - i+1;//如果后面有个数小于前面,在前面序列中有mid-i+1个数比他大,也就是逆序数为mid-i+1,前i-1个都是小于后面这个数的 } } while (i != mid+1)//如果一个序列提前走完,把另个序列剩下的全赋值到后面 b[k++] = a[i++]; while (j != right+1) b[k++] = a[j++]; for (i = left; i <= right; i++) a[i] = b[i];}void sever(int*a,int*b,int left,int right){ //建树函数 int mid; if(left < right) { mid = (left + right) / 2; sever(a, b, left, mid); sever(a, b, mid + 1, right);//先递归到底,再自底向上合并 fix(a, b, left, mid, right); }}int main(){ int n,i; while (scanf("%d", &n), n != 0) { num = 0; for (i = 0; i < n; i++) scanf("%d", &a[i]); sever(a, b, 0, n-1); printf("%I64d\n", num);//这里要用%I64d(i的大写) } return 0;}
求逆序数最典型的方法是用树状数组,所以这道题还可以用树状数组做
代码如下:
#include <iostream>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <algorithm>using namespace std;const int maxn= 500005;int aa[maxn];//离散化后的数组int c[maxn]; //树状数组int n;struct Node{ int v; int order;}a[maxn];bool cmp(Node a, Node b){ return a.v < b.v;}int lowbit(int k){ return k&(-k); //基本的lowbit函数 }void update(int t, int value){ //即一开始都为0,一个个往上加(+1), int i; for (i = t; i <= n; i += lowbit(i)) c[i] += value; }int getsum(int t){ //即就是求和函数,求前面和多少就是小于它的个数 int i, sum = 0; for (i = t; i >= 1; i -= lowbit(i)) sum += c[i]; return sum;}int main(){ int i; while (scanf("%d", &n), n) { for (i = 1; i <= n; i++) //离散化 { scanf("%d", &a[i].v); a[i].order = i; } sort(a + 1, a + n + 1,cmp);//从1到n排序,cmp容易忘 memset(c, 0, sizeof(c)); for (i = 1; i <= n; i++) aa[a[i].order] = i; __int64 ans = 0; for (i = 1; i <= n; i++) { update(aa[i], 1); ans += i - getsum(aa[i]); //减去小于的数即为大于的数即为逆序数 } printf("%I64d\n", ans); } return 0;}
0 0
- POJ2299 Ultra-QuickSort 归并排序和逆序数,树状数组
- poj2299 Ultra-QuickSort&&NYOJ117 求逆序数 (树状数组求逆序对数+离散化)+(归并排序)
- POJ2299 Ultra-QuickSort【树状数组】【逆序数】
- POJ Ultra-QuickSort 逆序数 树状数组 归并排序
- POJ2299 Ultra-QuickSort 归并排序求逆序数对
- POJ2299《Ultra-QuickSort》方法:归并排序找逆序数
- (归并排序求逆序数) poj2299 Ultra-QuickSort
- POJ2299-Ultra-QuickSort (归并排序求逆序数)
- POJ2299 Ultra-QuickSort (归并排序求逆序数模板)
- Ultra-QuickSort poj2299 (归并排序 求逆序数对)
- POJ2299 Ultra-QuickSort(归并排序,求逆序数)
- POJ2299 Ultra-QuickSort(树状数组求逆序数)
- POJ2299:Ultra-QuickSort(树状数组求逆序数)
- POJ2299 Ultra-QuickSort(逆序数问题,树状数组求解)
- poj2299 Ultra-QuickSort(归并排序 || 离散化+树状数组)
- poj2299 Ultra-QuickSort/nyoj117(树状数组,归并排序)
- POJ 2299 Ultra-QuickSort 【归并排序求逆序数 OR 树状数组求逆序数】
- 【树状数组】poj2299 Ultra-QuickSort(离散化+树状数组求逆序数)
- UIWindow和UIView
- Fedora系统初次安装与配置(兼容win10双系统)
- Makefile浅析(一)
- [Leetcode]Sqrt(x)
- 视觉识别领域会议列表
- POJ2299 Ultra-QuickSort 归并排序和逆序数,树状数组
- sharesdk分享qq空间-错误码1001
- c++primer第五版第十二章练习
- 用php写每天固定时间要执行的代码
- 【HDU 1005】Number Sequence
- ViewController
- view 中的 opaque , alpha , 和 alpha 的区别
- 使用JavaScript实现一个“字节码解释器”,并用它重新实现JS科学计算器的后端(后续1)
- Blog 收藏