题目传送门

 /*
题意:就是要求冒泡排序的交换次数。
逆序数:在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。
一个排列中逆序的总数就称为这个排列的逆序数。逆序数为偶数的排列称为偶排列;逆序数为奇数的排列称为奇排列。
如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的更多相关文章

  1. 归并排序求逆序对(poj 2299)

    归并排序求逆序对 题目大意 给你多个序列,让你求出每个序列中逆序对的数量. 输入:每组数据以一个数 n 开头,以下n行,每行一个数字,代表这个序列: 输出:对于输出对应该组数据的逆序对的数量: 顺便在 ...

  2. POJ 2299 Ultra-QuickSort 逆序数 树状数组 归并排序 线段树

    题目链接:http://poj.org/problem?id=2299 求逆序数的经典题,求逆序数可用树状数组,归并排序,线段树求解,本文给出树状数组,归并排序,线段树的解法. 归并排序: #incl ...

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

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

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

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

  5. poj 2299 逆序数

    http://poj.org/problem?id=2299 坑:答案是long long 输出……!!!!! 题意是:求一个数组进行冒泡排序交换的次数 题解:求逆序数 题解Ⅰ: 归并排序求逆序数 归 ...

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

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

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

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

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

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

  9. poj 2299 Ultra-QuickSort :归并排序求逆序数

    点击打开链接 Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 34676   Accepted ...

随机推荐

  1. CSS3实现二十多种基本图形

    CSS3可以实现很多漂亮的图形,我收集了32种图形,在下面列出.直接用CSS3画出这些图形,要比贴图性能更好,体验更加,是一种非常好的网页美观方式. 这32种图形分别为圆形,椭圆形,三角形,倒三角形, ...

  2. Android通过URL加载网络图片

    public static Bitmap getBitmap(String path) throws IOException { URL url = new URL(path); HttpURLCon ...

  3. Nmap备忘单:从探索到漏洞利用(Part3)

    众所周知NMAP是经常用来进行端口发现.端口识别.除此之外我们还可以通过NMAP的NSE脚本做很多事情,比如邮件指纹识别,检索WHOIS记录,使用UDP服务等. 发现地理位置 Gorjan Petro ...

  4. 我常用的delphi 第三方控件

    转载:http://www.cnblogs.com/xalion/archive/2012/01/09/2317246.html 有网友问我常用的控件及功能.我先大概整理一下,以后会在文章里面碰到时再 ...

  5. HDU1068 最大独立点集

    Girls and Boys Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  6. poj1611(感染病患者)

    The Suspects Time Limit: 1000MS   Memory Limit: 20000K Total Submissions: 24587   Accepted: 12046 De ...

  7. [ruby on rails] 跟我学之(3)基于rails console的查增删改操作

    本章节展开对model的介绍:包括查增删改操作.紧接着上面一节<[ruby on rails] 跟我学之HelloWorld> 创建模型 使用命令创建模型 创建表post,默认自带两栏位 ...

  8. 【云计算】Dockerfile、镜像、容器快速入门

    Dockerfile.镜像.容器快速入门 1.1.Dockerfile书写示例 Dockerfile可以用来生成Docker镜像,它明确的定义了Image的生成过程.虽然直接修改容器也可以提交生成镜像 ...

  9. 转MYSQL学习(五) 索引

    索引是在存储引擎中实现的,因此每种存储引擎的索引都不一定完全相同,并且每种存储引擎也不一定支持所有索引类型. 根据存储引擎定义每个表的最大索引数和最大索引长度.所有存储引擎支持每个表至少16个索引,总 ...

  10. 用数据表创建树_delphi教程

    数据库结构:字段 类型ID 整型 索引(无重复)name 文本father 整型 //tree初始化procedure TForm1.FormActivate(Sender: TObject);var ...