poj2299Ultra-QuickSort【树状数组求逆序数、离散化】、【归并排序模板】
来源:互联网 发布:手机电脑屏幕同步软件 编辑:程序博客网 时间:2024/05/16 15:34
Description
In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence
9 1 0 5 4 ,
Ultra-QuickSort produces the output
0 1 4 5 9 .
Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.
Ultra-QuickSort produces the output
Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.
Input
The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.
Output
For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.
Sample Input
59105431230
Sample Output
60
Source
Waterloo local 2005.02.05
搁浅了好久了树状数组,尤其是在两天都被操作系统虐的不行不行的情况下,捡起本来就不咋熟练的这货还是有些费事。
这次的专题没做裸的树状数组,逆序数算是树状数组里面比较典型的应用了,尤其是500,000的数据量需要用到离散化,啥是离散化?
以这个题为例,手写了一下中间变量的输出:原数组是9,1,0,5,4 离散后变成了5,2,1,4,3大大缩减了空间开销,这里需要着重注意一下~~
再就说道求逆序数的原理:查询函数返回在序列中比这个数小的个数,假定序列中第i个数为a,那么前i个数中比i大的元素个数为i-sum(i)。当然了,求之前需要调用add函数,函数的第一个参数本来是位置,在这个题中当然带进去的也是离散后的相对位置,貌似说的不是特别明白==
用最原始的树状数组来说明,数组A代表数字i在序列中是否出现过,如果已经存在,那么A【i】=1,否则等于0,,此时查询函数返回值为序列中比数字i小的个数。因为是一位一位add进去,增加一个查询一个,出现了一个数x,则a[x]=1,暂时没出现的就是0,查询的是当前这个数以前的,那么答案显而易见啦
/***************2016.2.1poj22778152K391MSG++1129B***************/#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define maxn 500005int n;int c[maxn],b[maxn];struct Node{ int index,v;}node[maxn];bool cmp(Node a,Node b){ return a.v<b.v;}int lowbit(int x){ return x&(-x);}void add(int i,int val){ while(i<=n) { c[i]+=val; i+=lowbit(i); }}int sum(int i){ int s=0; while(i>0) { s+=c[i]; i-=lowbit(i); } return s;}int main(){ //freopen("cin.txt","r",stdin); while(~scanf("%d",&n)&&n) { for(int i=1;i<=n;i++) { scanf("%d",&node[i].v); node[i].index=i; } memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); sort(node+1,node+1+n,cmp); b[node[1].index]=1; for(int i=2;i<=n;i++) { b[node[i].index]=i; } long long ans=0; for(int i=1;i<=n;i++) { add(b[i],1); ans+=(i-sum(b[i])); } printf("%I64d\n",ans); } return 0;}
不是自己的代码,但是是裸的应用,没必要再写一遍是吧
#include <stdio.h>#include<string.h>#include<iostream>using namespace std;const int MAXN=500010;long long ans;//存放逆序数,比较大,必须用long longint a[MAXN],b[MAXN],c[MAXN];//将已经排好序的left~mid,mid+1~right进行归并void merge(int *a,int left,int mid,int right){ int i,j; i=0; for(j=left;j<=mid;j++) b[i++]=a[j]; int len1=mid-left+1; i=0; for(j=mid+1;j<=right;j++) c[i++]=a[j]; int len2=right-mid; i=0; j=0; int k=left; while(i<len1&&j<len2&&k<=right) { if(b[i]<=c[j]) { a[k++]=b[i++]; } else { a[k++]=c[j++]; ans+=(len1-i);//逆序数就是累加后面比自己小的数的个数 //此时b[i]>c[j],那么c[j]会给b[i]后面的len1-i个数造成逆序数 } } while(i<len1) a[k++]=b[i++]; while(j<len2) a[k++]=c[j++];}void merge_sort(int *a,int left,int right)//对a[left~right-1]进行归并排序{ if(left<right) { int mid=(left+right)/2; merge_sort(a,left,mid); merge_sort(a,mid+1,right); merge(a,left,mid,right); }}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n; while(scanf("%d",&n),n) { for(int i=0;i<n;i++) scanf("%d",&a[i]); ans=0; merge_sort(a,0,n-1); printf("%I64d\n",ans); } return 0;}
0 0
- poj2299Ultra-QuickSort【树状数组求逆序数、离散化】、【归并排序模板】
- 树状数组+离散化求逆序数poj2299Ultra-QuickSort
- poj2299 Ultra-QuickSort&&NYOJ117 求逆序数 (树状数组求逆序对数+离散化)+(归并排序)
- nyoj117求逆序数(离散化+树状数组/归并排序)
- poj2299Ultra-QuickSort(归并求逆序数)
- poj2299Ultra-QuickSort【线段树求逆序数】离散化
- 求逆序数模板(树状数组+离散化 || 归并排序法)
- poj2299Ultra-QuickSort(归并排序+树状数组)
- POJ 2299 Ultra-QuickSort(树状数组+离散化 或 归并排序求逆序)
- poj2299Ultra-QuickSort(树状数组+离散化)
- Ultra-QuickSort(离散化+树状数组求逆序数)
- POJ 2299 Ultra-QuickSort 【归并排序求逆序数 OR 树状数组求逆序数】
- poj 2299 Ultra-QuickSort 线段树求逆序数+离散化||归并排序求逆序数
- 南阳117求逆序数(离散化+树状数组或归并排序)
- 【树状数组】poj2299 Ultra-QuickSort(离散化+树状数组求逆序数)
- 树状数组求逆序数的模板(离散化处理)
- 归并排序&&树状数组求逆序数
- 归并排序 树状数组 求逆序数
- Linux极客命令(基础篇)
- SQL session vs global
- hibernate 持久化类要求
- centos搭建nginx流媒体服务器不出现client_body_temp等文件目录的问题
- 登陆注册的邮箱格式判断
- poj2299Ultra-QuickSort【树状数组求逆序数、离散化】、【归并排序模板】
- codeforces621B. Wet Shark and Bishops
- 出现( linker command failed with exit code 1)错误总结
- 用python调用C/C++的两种方式
- 构建高并发高可用的电商平台架构实践
- Handlebars的使用
- hdu 5074(简单dp)
- 大型网站图片服务器架构的演进
- mysql备份