逆序数 POJ 2299 Ultra-QuickSort
/*
题意:就是要求冒泡排序的交换次数。
逆序数:在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。
一个排列中逆序的总数就称为这个排列的逆序数。逆序数为偶数的排列称为偶排列;逆序数为奇数的排列称为奇排列。
如2431中,21,43,41,31是逆序,逆序数是4,为偶排列。也是就说,对于n个不同的元素,
先规定各元素之间有一个标准次序(例如n个 不同的自然数,可规定从小到大为标准次序),于是在这n个元素的任一排列中,
当某两个元素的先后次序与标准次序不同时,就说有1个逆序。一个排列中所有逆序总数叫做这个排列的逆序数。 接下来有多种做法求解逆序数:1. 暴力;2. 归并排序;3. 线段树-单点更新;4. 树状数组
*/
/*
暴力 超时 O(n^2)
*/
#include <stdio.h> const int MAX_N = ;
int a[MAX_N+];
long long cnt = ; int main(void) //POJ 2299 Ultra-QuickSort
{
//freopen ("inD.txt", "r", stdin);
int n; while (scanf ("%d", &n) != EOF && n)
{
for (int i=; i<=n; ++i)
{
scanf ("%d", &a[i]);
} for (int i=; i<=n; ++i)
{
for (int j=i+; j<=n; ++j)
{
if (a[i] > a[j])
cnt++;
}
}
printf ("%lld\n", cnt);
cnt = ;
} return ;
}
暴力 超时 O(n^2)
/*
归并排序是将数列a[p, r]分成两半a[p, q]和a[q+1,r]分别进行归并排序,
然后再将这两半合并起来。在合并的过程中(设p<=i<=q,q+1<=j<=r),
当L[i]<=R[j]时,并不产生逆序数;
当L[i]>R[j]时,在前半部分中比L[i]大的数都比R[j]大,
将R[j]放在L[i]前面的话,逆序数要加上q+1-i。
因此,可以在归并排序中的合并过程中计算逆序数。 这道题充分印证了,即使merge本身可能用的不多,但分冶的思想却是无所不在:)
*/
#include <stdio.h> const int MAX_N = ;
const int INF = 0xffffff;
int a[MAX_N+];
long long cnt = ; void Merge(int *a, int p, int q, int r)
{
int n1 = q - p + ;
int n2 = r - q;
int L[MAX_N/+], R[MAX_N/+];
int i, j;
for (i=; i<=n1; ++i) L[i] = a[p+i-];
for (j=; j<=n2; ++j) R[j] = a[q+j];
L[n1+] = INF; R[n2+] = INF; i = ; j = ;
for (int k=p; k<=r; ++k)
{
if (L[i] <= R[j])
{
a[k] = L[i++];
}
else
{
a[k] = R[j++];
cnt += n1 - i + ; //此步骤是在归并排序法中加的一句,用来计数求逆序数的数目
}
}
} void MergeSort(int *a, int p, int r)
{
int q;
if (p < r)
{
q = (p + r) / ;
MergeSort (a, p, q);
MergeSort (a, q+, r);
Merge (a, p, q, r);
}
} int main(void) //POJ 2299 Ultra-QuickSort
{
//freopen ("inD.txt", "r", stdin);
int n; while (scanf ("%d", &n) != EOF && n)
{
for (int i=; i<=n; ++i)
{
scanf ("%d", &a[i]);
}
MergeSort (a, , n);
printf ("%lld\n", cnt);
cnt = ;
} return ;
}
归并排序
/*
线段树-单点更新
*/
#include <cstdio>
#include <algorithm>
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1
using namespace std; const int MAX_N = ;
const int INF = 0x3f3f3f3f;
int a[MAX_N];
int b[MAX_N];
int sum[MAX_N << ]; void pushup(int rt)
{
sum[rt] = sum[rt << ] + sum[rt << | ];
} void build(int l, int r, int rt)
{
sum[rt] = ;
if (l == r) return ;
int m = (l + r) >> ;
build (lson);
build (rson); pushup (rt);
} void update(int p, int l, int r, int rt)
{
if (l == r)
{
sum[rt]++; //记录次数
return ;
}
int m = (l + r) >> ;
if (p <= m)
{
update (p, lson);
}
else
update(p, rson);
pushup (rt);
} int query(int ql, int qr, int l, int r, int rt)
{
if (ql <= l && r <= qr)
{
return sum[rt];
}
int m = (l + r) >> ;
int ans = ;
if (ql <= m) ans += query (ql, qr, lson);
if (qr > m) ans += query (ql, qr, rson); return ans;
} int BinarySearch(int key, int l, int r)
{
while (r >= l)
{
int mid = (l + r) >> ;
if (key == b[mid]) return mid;
if (key < b[mid]) r = mid - ;
else l = mid + ;
}
} int main(void)
{
//freopen ("inD.txt", "r", stdin);
int n;
while (~scanf ("%d", &n) && n)
{
build (, n-, ); for (int i=; i<=n; ++i)
{
scanf ("%d", &a[i]);
b[i] = a[i];
}
sort (b+, b+n+);
long long ans = ;
for (int i=; i<=n; ++i)
{
int x = BinarySearch (a[i], , n);
ans += query (x, n, , n, );
update (x, , n, );
}
printf ("%lld\n", ans);
} return ;
}
线段树-单点更新
逆序数 POJ 2299 Ultra-QuickSort的更多相关文章
- 归并排序求逆序对(poj 2299)
归并排序求逆序对 题目大意 给你多个序列,让你求出每个序列中逆序对的数量. 输入:每组数据以一个数 n 开头,以下n行,每行一个数字,代表这个序列: 输出:对于输出对应该组数据的逆序对的数量: 顺便在 ...
- POJ 2299 Ultra-QuickSort 逆序数 树状数组 归并排序 线段树
题目链接:http://poj.org/problem?id=2299 求逆序数的经典题,求逆序数可用树状数组,归并排序,线段树求解,本文给出树状数组,归并排序,线段树的解法. 归并排序: #incl ...
- poj 2299 Ultra-QuickSort (归并排序 求逆序数)
题目:http://poj.org/problem?id=2299 这个题目实际就是求逆序数,注意 long long 上白书上的模板 #include <iostream> #inclu ...
- POJ 2299 Ultra-QuickSort 归并排序、二叉排序树,求逆序数
题目链接: http://poj.org/problem?id=2299 题意就是求冒泡排序的交换次数,显然直接冒泡会超时,所以需要高效的方法求逆序数. 利用归并排序求解,内存和耗时都比较少, 但是有 ...
- poj 2299 逆序数
http://poj.org/problem?id=2299 坑:答案是long long 输出……!!!!! 题意是:求一个数组进行冒泡排序交换的次数 题解:求逆序数 题解Ⅰ: 归并排序求逆序数 归 ...
- poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)
题目链接:http://poj.org/problem?id=2299 Description In this problem, you have to analyze a particular so ...
- poj 2299 Ultra-QuickSort(树状数组求逆序数)
链接:http://poj.org/problem?id=2299 题意:给出n个数,求将这n个数从小到大排序,求使用快排的需要交换的次数. 分析:由快排的性质很容易发现,只需要求每个数的逆序数累加起 ...
- poj 2299 Ultra-QuickSort 归并排序求逆序数对
题目链接: http://poj.org/problem?id=2299 题目描述: 给一个有n(n<=500000)个数的杂乱序列,问:如果用冒泡排序,把这n个数排成升序,需要交换几次? 解题 ...
- poj 2299 Ultra-QuickSort :归并排序求逆序数
点击打开链接 Ultra-QuickSort Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 34676 Accepted ...
随机推荐
- mac os 安装 pkg-config
wget http://pkgconfig.freedesktop.org/releases/pkg-config-0.29.tar.gz . env LDFLAGS="-framework ...
- 数据库多张表导出到excel
数据库多张表导出到excel public static void export() throws Exception{ //声明需要导出的数据库 String dbName = "hdcl ...
- CC MayClg 15 T3
www.codechef.com/MAY15/problems/CHAPD 一道比较神奇的题目... 看到题目后自己yy出了个傻逼算法...然后对拍都是对的...提交都是错的...然后一看" ...
- 已知局域网IP地址,如何查看mac
arp -a 加对方IP是查对方的MAC地址 转自: http://zhidao.baidu.com/link?url=8sRdpGcjfGQ-C1F9zNub49Mxe3DAR-RCAHDkHvKC ...
- 基础知识《二》java的基本类型
一.java基本数据类型 Java基本类型共有八种,基本类型可以分为三类,字符类型char,布尔类型boolean以及数值类型byte.short.int.long.float.double.数值类型 ...
- HDFS 原理、架构与特性介绍--转载
原文地址:http://www.uml.org.cn/sjjm/201309044.asp 本文主要讲述 HDFS原理-架构.副本机制.HDFS负载均衡.机架感知.健壮性.文件删除恢复机制 1:当前H ...
- h5在微信中不允许放大缩小页面
在头部添加 <meta name="viewport" content="width=device-width, initial-scale=1, maximum- ...
- sockaddr struct 类型重定义
windows.h和winsock2.h有类型重定义我是知道的,本来就一个库来说没问题,把winsock2放到windows.h前或先定义WIN32_LEAN_AND_MEAN都能解决问题但现的出了问 ...
- Heap:Sunscreen(POJ 3614)
晒太阳 题目大意:一堆牛,为了避免晒太阳会灼烧自己,然后他们自己有自己的防晒指数(一个区间),防晒霜可以提高防晒因数SPF,大了不行小了不行,现在有一桶防晒霜,他们提供一定的SPF,但是最多可以提供k ...
- UESTC 1215 (思维题 旋转)
Secrete Master Plan Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Othe ...