归并排序求逆序对数 (附另两种姿势BIT 线段树)
来源:互联网 发布:cygwin 运行linux程序 编辑:程序博客网 时间:2024/06/11 08:31
求逆序数 三种方法 归并排序 树状数组 线段树
交换次数即为逆序对数
poj1804数据范围小,int不会溢出,spoj上提价需用long long(注册spoj时,获取验证码时会访问谷歌,所以需要……)
#define _CRT_SECURE_NO_WARNINGS#include <cstdio>#include <cstring>const int maxn = 2e5 + 7;int a[maxn], b[maxn];long long cnt;//函数里有个全局变零cnt保存交换次数,即1逆序数。对ary[l:r]排序,函数结束后,ary = desvoid merge_sort(int ary[], int l, int r, int des[]) { //对ary[l..r]进行归并排序 if (l >= r) return;int mid = (l + r) >> 1;merge_sort(ary, l, mid, des);merge_sort(ary, mid + 1, r, des);int i = l, j = mid + 1, cur = l; //下面是合并while (i <= mid && j <= r) {if (ary[i] <= ary[j]) {des[cur++] = ary[i++];}else { //逆序啦,ary[i] > ary[j], ary[j]要调到前(左)面des[cur++] = ary[j++];cnt += mid - i + 1; //关键看这里//当ary[i] > ary[j]时,在前半部分中比ary[i]大的数都比ary[j]大,将ary[j]放在ary[i]前面的话,逆序数要加上mid + 1 - i}}while (i <= mid) {des[cur++] = ary[i++];}while (j <= r) {des[cur++] = ary[j++];}memcpy(ary + l, des + l, sizeof(int) * (r - l + 1));} int main(){int T;scanf("%d", &T);for (int k = 1; k <= T; ++k) {int n;scanf("%d", &n);cnt = 0;for (int i = 0; i < n; ++i)scanf("%d", a + i);merge_sort(a, 0, n - 1, b);//printf("%d", b[0]);//for (int i = 1; i < n; ++i)//printf(" %d", b[i]);//puts(""); //检验归并排序是否正确//printf("Scenario #%d:\n%d\n\n", k, cnt); //poj1804提交姿势,poj上数据范围小,int不会溢出printf("%lld\n", cnt); //http://www.spoj.com/problems/INVCNT/en/}return 0;}
BIT解法(适用于POJ1804)
#include <cstdio>#include <cstring>#define ADD 1000001#define M 2000001#define N 1007 using namespace std;int ary[N], bit[M + 1], n;int lowbit(int x) {return x & (-x);}void add(int pos, int val) {while(pos <= M) { //pos <= ?bit[pos] += val;pos += lowbit(pos);}}int sum(int pos) { //询问1:pos的和 int res = 0;while(pos > 0) {res += bit[pos];pos -= lowbit(pos);}return res;}int main() {int T, kase = 0;scanf("%d", &T);while (T-- > 0) {memset(bit, 0, sizeof bit);scanf("%d", &n);long long ans = 0; for (int i = 0; i < n; ++i) {scanf("%d", ary + i);ary[i] += ADD;ans += (i - sum(ary[i])); //这两句难理解 add(ary[i], 1);}printf("Scenario #%d:\n%lld\n\n", ++kase, ans);} return 0;}
hdu1394
#define _CRT_SECURE_NO_WARNINGS#include <cstdio>#include <algorithm>#include <cstring>using namespace std;const int N = 5007;int segTree[N << 1], ary[N];void build(int rt, int l, int r) {segTree[rt] = 0;if (l == r) return;int mid = l + r >> 1;build(rt << 1, l, mid);build(rt << 1 | 1, mid + 1, r);}void update(int rt, int l, int r, int pos) {if (l == r) {segTree[rt]++; //因为是求逆序数,所以加1return;}int mid = l + r >> 1;if (pos <= mid)update(rt << 1, l, mid, pos);else update(rt << 1 | 1, mid + 1, r, pos);segTree[rt] = segTree[rt << 1] + segTree[rt << 1 | 1]; //别忘了更新父节点}int query(int rt, int l, int r, int L, int R) {if (L <= l && r <= R) {return segTree[rt];}int mid = l + r >> 1, res = 0;if (L <= mid)res += query(rt << 1, l, mid, L, R);if (R > mid)res += query(rt << 1 | 1, mid + 1, r, L, R);return res;}int main(){int n;while (~scanf("%d", &n)) {memset(segTree, 0, sizeof segTree);int cnt = 0;for (int i = 0; i < n; ++i) {scanf("%d", ary + i);cnt += query(1, 0, n - 1, ary[i], n - 1);update(1, 0, n - 1, ary[i]); //动态更新}int minCnt = cnt;for (int i = 0; i < n; ++i) {cnt += n - ary[i] - ary[i] - 1; //这一步操作可以求得队首元素放到队尾的逆序数,前提是数组ary[i]是0:n-1的一个排列minCnt = min(minCnt, cnt);}printf("%d\n", minCnt);}return 0;}
阅读全文
0 0
- 归并排序求逆序对数 (附另两种姿势BIT 线段树)
- HDU 1394 Minimum Inversion Number(线段树/归并排序求逆序对数)
- 求逆序对数(利用归并排序)
- 归并排序求逆序对数)
- 归并排序&求逆序对数
- 归并排序求逆序对数
- 归并排序求逆序对数
- 归并排序求逆序对数
- 求逆序对数的NLogN解法:归并排序、树状数组和线段树
- hdu1394(线段树求逆序对数)
- 逆序对数(归并排序)
- POJ 2299 Ultra-QuickSort(归并排序求逆序对数)
- POJ 1804 Brainman (归并排序 -- 求逆序对数)
- POJ 2299 归并排序 求逆序对数
- 归并排序算法求逆序对数
- 算法1:求逆序对数与显著逆序对数(归并排序)
- POJ 2299 Ultra-QuickSort(逆序对数,线段树/树状数组/归并排序)
- 归并求逆序对数
- 分析linux011版本中inode节点使用直接块,间接块所能表示的一个文件的大小
- 入门经典_Chap06_例题[四]:最后四题
- chrome 打开视频网站提示需要安装flash player(没有安装flash ,请先下载)
- Windows Server R2 2012安装mysql-5.7.13-winx64
- MySQL将查询结果插入到数据表中
- 归并排序求逆序对数 (附另两种姿势BIT 线段树)
- servlet和Jsp生命周期解读
- 【PAT甲级】1078. Hashing (25)
- java-Exectors提供的四种基本线程池用法与比较详解
- Java 图片地址全部路径与相对路径替换
- SQL优化指南——优化工具使用
- 解题报告: Codeforces 396A. On Number of Decompositions into Multipliers 组合
- chrome开发者工具使用
- JS手机号正则验证