题目传送门

 /*
题意:就是要求冒泡排序的交换次数。
逆序数:在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。
一个排列中逆序的总数就称为这个排列的逆序数。逆序数为偶数的排列称为偶排列;逆序数为奇数的排列称为奇排列。
如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. 解决ie文本框不能输入和获取焦点问题

    解决办法:    从正常的机器上拷贝c:\windows\system32\mshtmled.dll到本机的system32目录下即可.或者从安装盘中提取该文件.    加载mshtmled.dll: ...

  2. django LDAP

    > http://goodosoft.github.io/2015/02/25/Using-AD-as-authentication-for-Django/ > http://my.osc ...

  3. 【转】打造属于自己的Android Studio神器

    本文转载自:http://www.stormzhang.com/android/2015/05/26/android-tools/,并加以修改.黄色底部分是本人添加的内容. 一晃好久没更新博客了,最近 ...

  4. Android Studio项目引入外部库注意事项(PullToRefresh)

    Android Studio开发App项目时引入第三方库是个比较麻烦的事情.之前导入Volley就折腾了好久,导入下拉刷新控件PullToRefresh时又碰到了各种问题.在此记录一下,以便查阅. 一 ...

  5. cocos2dx3.0rc导出自定义类到lua的方法

    以前要导出c++类到lua,就得手动维护pkg文件,那简直就是噩梦,3.0以后就会感觉生活很轻松了. 转载请注明出处http://www.cnblogs.com/mrblue/p/3637910.ht ...

  6. HDU2018递推牛

    母牛的故事 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  7. Codeforces 424A (思维题)

    Squats Time Limit: 1000MS   Memory Limit: 262144KB   64bit IO Format: %I64d & %I64u Submit Statu ...

  8. [Android Pro] Android 打包流程

    Android 打包流程: 官网地址:http://developer.android.com/tools/building/index.html 具体的打包步骤如下: 1:生成R.java类文件:E ...

  9. 玩转Chrome workplace

    简介 相信大家都知道Chrome Develop Tools中的workplace,这使得我们能够让本地的文件夹在Source面板下可以编辑.没错,这使得chrome同样可以成为我们可选的编辑器之一, ...

  10. markdown下编辑latex数学公式

    在利用为知笔记编写笔记的时候,有时需要用的markdown,只要把文件名加上后缀.md,就可以使用markdown语法,以下介绍在markdown下编辑latex数学公式. 使用LaTeX写公式的基本 ...