Ultra-QuickSort
Time Limit: 7000MS   Memory Limit: 65536K
Total Submissions: 70674   Accepted: 26538

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.

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

5
9
1
0
5
4
3
1
2
3
0

Sample Output

6
0

Source

 
题目意思:
对于给定的无序数组
求除经过多少次相邻的元素交换之后,可以使得数组升序
就是求一个数列的逆序数
 
 
方法一:
树状数组求解逆序数
从头到尾读入这些数,每读入一个数就更新树状数组,
查看它前面比它小的已出现过的有多少个数sum,
然后用当前位置减去该sum,
就可以得到当前数导致的逆序对数了。
把所有的加起来就是总的逆序对数。
code:
#include<queue>
#include<set>
#include<cstdio>
#include <iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define max_v 500005
int n;
struct node
{
int v;
int pos;
} p[max_v];
int c[max_v];
int re[max_v];
int maxx;
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int d)
{
while(x<=n)
{
c[x]+=d;
x+=lowbit(x);
}
}
int getsum(int x)
{
int res=;
while(x>)
{
res+=c[x];
x-=lowbit(x);
}
return res;
}
bool cmp(node a,node b)
{
return a.v<b.v;
}
int main()
{
while(~scanf("%d",&n))
{
if(n==)
break;
memset(c,,sizeof(c));
for(int i=;i<=n;i++)
{
scanf("%d",&p[i].v);
p[i].pos=i;
} sort(p+,p++n,cmp);
for(int i=;i<=n;i++)
{
re[p[i].pos]=i;//离散化
} long long ans=;
for(int i=;i<=n;i++)
{
update(re[i],);
ans+=(i-getsum(re[i]));//当前位置减去前面比它小的数的个数之和就是答案
}
printf("%lld\n",ans);
}
return ;
}
/*
题目意思:
对于给定的无序数组
求除经过多少次相邻的元素交换之后,可以使得数组升序
就是求一个数列的逆序数 从头到尾读入这些数,每读入一个数就更新树状数组,
查看它前面比它小的已出现过的有多少个数sum,
然后用当前位置减去该sum,
就可以得到当前数导致的逆序对数了。
把所有的加起来就是总的逆序对数。
*/

感觉自己的树状数组这样写真的是傻的一批,离散化写的麻烦了,照着别人的离散化写的!

现在明白了离散化是什么东西:就是数据范围压缩!!!

贴一个自己离散化的代码

#include<queue>
#include<set>
#include<cstdio>
#include <iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define max_v 500005
int n;
struct node
{
int v;
int pos;
} p[max_v];
int c[max_v];
int re[max_v];
int maxx;
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int d)
{
while(x<max_v)
{
c[x]+=d;
x+=lowbit(x);
}
}
int getsum(int x)//返回1到x中小与等于x的数量
{
int res=;
while(x>)
{
res+=c[x];
x-=lowbit(x);
}
return res;
}
bool cmp(node a,node b)
{
if(a.v!=b.v)
return a.v<b.v;
else
return a.pos<b.pos;
}
int main()
{
while(~scanf("%d",&n))
{
if(n==)
break;
memset(c,,sizeof(c));
for(int i=;i<=n;i++)
{
scanf("%d",&p[i].v);
p[i].pos=i;
} sort(p+,p++n,cmp); long long ans=;
for(int i=;i<=n;i++)
{
ans+=(i-getsum(p[i].pos)-);//先找再更新,避免getsum的时候算上自己
update(p[i].pos,);
}
printf("%lld\n",ans);
}
return ;
}

方法二:归并排序求解逆序数

在归并排序的过程中,比较关键的是通过递归,
将两个已经排好序的数组合并,
此时,若a[i] > a[j],则i到m之间的数都大于a[j],
合并时a[j]插到了a[i]之前,此时也就产生的m-i+1个逆序数,
而小于等于的情况并不会产生。

code:

#include<stdio.h>
#include<memory>
#define max_v 500005
typedef long long LL;
LL a[max_v];
LL temp[max_v];
LL ans;
void mer(int s,int m,int t)
{
int i=s;
int j=m+;
int k=s;
while(i<=m&&j<=t)
{
if(a[i]<=a[j])
{
temp[k++]=a[i++];
}else
{
ans+=j-k;//求逆序数
temp[k++]=a[j++];
}
}
while(i<=m)
{
temp[k++]=a[i++];
}
while(j<=t)
{
temp[k++]=a[j++];
}
}
void cop(int s,int t)
{
for(int i=s;i<=t;i++)
a[i]=temp[i];
}
int megsort(int s,int t)
{
if(s<t)
{
int m=(s+t)/;
megsort(s,m);
megsort(m+,t);
mer(s,m,t);
cop(s,t);
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
if(n==)
break;
ans=;
for(int i=;i<n;i++)
scanf("%lld",&a[i]);
megsort(,n-);
printf("%lld\n",ans);
}
return ;
}
/*
题目意思:
对于给定的无序数组
求除经过多少次相邻的元素交换之后,可以使得数组升序
就是求一个数列的逆序数 在归并排序的过程中,比较关键的是通过递归,
将两个已经排好序的数组合并,
此时,若a[i] > a[j],则i到m之间的数都大于a[j],
合并时a[j]插到了a[i]之前,此时也就产生的m-i+1个逆序数,
而小于等于的情况并不会产生。
*/
 

POJ 2299 Ultra-QuickSort 求逆序数 (归并或者数状数组)此题为树状数组入门题!!!的更多相关文章

  1. poj 2299 Ultra-QuickSort (归并排序 求逆序数)

    题目:http://poj.org/problem?id=2299 这个题目实际就是求逆序数,注意 long long 上白书上的模板 #include <iostream> #inclu ...

  2. poj 2299 Ultra-QuickSort 归并排序求逆序数对

    题目链接: http://poj.org/problem?id=2299 题目描述: 给一个有n(n<=500000)个数的杂乱序列,问:如果用冒泡排序,把这n个数排成升序,需要交换几次? 解题 ...

  3. Poj 2299 Ultra-QuickSort(归并排序求逆序数)

    一.题意 给定数组,求交换几次相邻元素能是数组有序. 二.题解 刚开始以为是水题,心想这不就是简单的冒泡排序么.但是毫无疑问地超时了,因为题目中n<500000,而冒泡排序总的平均时间复杂度为, ...

  4. nyoj 117 求逆序数 (归并(merge)排序)

    求逆序数 时间限制:2000 ms  |  内存限制:65535 KB 难度:5   描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中 ...

  5. poj 2299 Ultra-QuickSort(求逆序对)

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 52778   Accepted: 19348 ...

  6. POJ训练计划2299_Ultra-QuickSort(归并排序求逆序数)

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 39279   Accepted: 14163 ...

  7. POJ 2299 Ultra-QuickSort 归并排序、二叉排序树,求逆序数

    题目链接: http://poj.org/problem?id=2299 题意就是求冒泡排序的交换次数,显然直接冒泡会超时,所以需要高效的方法求逆序数. 利用归并排序求解,内存和耗时都比较少, 但是有 ...

  8. poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)

    题目链接:http://poj.org/problem?id=2299 Description In this problem, you have to analyze a particular so ...

  9. poj 2299 Ultra-QuickSort(树状数组求逆序数)

    链接:http://poj.org/problem?id=2299 题意:给出n个数,求将这n个数从小到大排序,求使用快排的需要交换的次数. 分析:由快排的性质很容易发现,只需要求每个数的逆序数累加起 ...

随机推荐

  1. 使用jQuery的validation插件实现表单校验

    前端表单校验: <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  2. Java枚举、静态导入、自动拆装箱、增强for循环、可变参数

    一.枚举简介 1.什么是枚举? 需要在一定范围内取值,这个值只能是这个范围内中的任意一个 现实场景:交通信号灯,有三种颜色,但是每次只能亮三种颜色里面的任意一个 2.使用一个关键字 enum enum ...

  3. [翻译]Review——Learn these core JavaScript concepts in just a few minutes

    Learn these core JavaScript concepts in just a few minutes(只需几分钟即可学习这些核心JavaScript概念) 原文地址:https://m ...

  4. Android学习笔记(4)----Rendering Problems(The graphics preview in the layout editor may not be accurate)

    在Android Studio中新建了一个 setting.xml 文件,布局好文件后,从 Text 界面切换到 Design 界面,显示了如下错误: 网上搜寻 The graphics previe ...

  5. SSM 框架-04-使用maven创建web项目

    SSM 框架-04-使用maven创建web项目 本篇介绍使用MAVEN来管理jar包,就不用一个一个去添加和下载jar包了,直接在maven配置文件中配置就可以了,maven可以帮助我们自动下载.本 ...

  6. vs2015生成的mvc模板结构说明

  7. Linux Swap扩容

    最近在做rac,在环境检查的时候发现swap空间检查不通过,所以我们第一想到的是对swap进行扩容,那么swap扩容有哪些方法呢?这里主要介绍两种方法,一通过添加额外磁盘,扩展swap分区,二是通过本 ...

  8. Mybatis学习---基础知识考核

    MyBatis 2.什么是MyBatis的接口绑定,有什么好处 接口映射就是在IBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定,    我们直接调用接口方法就可以,这样比起原来了Sql ...

  9. August 30th 2017 Week 35th Wednesday

    A lion does not concern himself with the opinion of sheep. 狮子可不会在意绵羊是怎么想的. As a sheep, you must run ...

  10. December 14th 2016 Week 51st Wednesday

    Everything has its time and that time must be watched. 万物皆有时,时来不可失. Everything has its time, and I r ...