Ultra-QuickSort---poj2299 (归并排序.逆序数.树状数组.离散化)
题目链接:http://poj.org/problem?id=2299
题意就是求把数组按从小到大的顺序排列,每次只能交换相邻的两个数, 求至少交换了几次
就是求逆序数
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 501000
using namespace std;
int a[N], b[N];
__int64 cnt; void Merge(int r, int mid, int l)
{
int i = r, j = mid+, k = ;
while(i<=mid && j<=l)
{
if(a[i] > a[j])
{
b[k++] = a[j++];
cnt += mid-i+; ///说明下标从i到mid的值都比a[j]大所以逆序数要+mid-i+1;
}
else if(a[i] < a[j])
{
b[k++] = a[i++];
}
else
{
b[k++] = a[i++];
j++;
}
}
while(i<=mid)
b[k++] = a[i++];
while(j<=l)
b[k++] = a[j++];
for(i=; i<k; i++)///将有序的临时数组 元素 刷回 被排序的数组 a 中,
a[i+r] = b[i];
} void MergeSort(int r, int l)
{
int mid = (r+l)/;
if(r < l)
{
MergeSort(r, mid);///对前半部分进行排序
MergeSort(mid + , l);///对后半部分进行排序
Merge(r, mid, l);/// 合并前后两部分
}
}
int main()
{
int n;
while(scanf("%d", &n),n)
{
cnt = ;
for(int i=; i<n; i++)
scanf("%d", &a[i]);
MergeSort(, n-);
printf("%I64d\n", cnt);
}
return ;
}
归并排序
用树状数组
序列3 5 4 8 2 6 9
大体思路为:新建一个数组,将数组中每个元素置0
0 0 0 0 0 0 0
取数列中最大的元素,将该元素所在位置置1 统计该位置前放置元素的个数,为0
0 0 0 0 0 0 1
接着放第二大元素8,将第四个位置置1 统计该位置前放置元素的个数,为0
0 0 0 1 0 0 1
继续放第三大元素6,将第六个位置置1 统计该位置前放置元素的个数,为1
0 0 0 1 0 1 1
…
这样直到把最小元素放完,累加每次放元素是该元素前边已放元素的个数,这样就算出总的逆序数来了在统计和计算每次放某个元素时,该元素前边已放元素的个数时如果一个一个地数,那么一趟复杂度为O(n),总共操
作n趟,复杂度为O(n^2),然而复杂度太大,
当然,在每次统计的过程中用树状数组可以把每一趟计数个数的复杂度降为O(logn),这样整个复杂度就变为O(nlogn)
树状数组是一种很好的数据结构,这有一篇专门描述树状数组的文章
将序列中的每个数按照从大到小的顺序插入到树状数组中,给当前插入节点及其到根节点之间的这条路径上的每个数加1,然后统计该节点右边放置元素的个数
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 501000
#define met(a, b) memset(a, b, sizeof(a)) int Hash[N], n;
__int64 Tree[N]; struct node
{
int V, id;
///重载运算符中:<是从大到小,>是从小到大;
friend bool operator < (node a, node b)
{
return a.V < b.V;
}
}a[N]; int lowbit(int x)
{
return x&(-x);
} void Update(int pos, int num)
{
while(pos<=n)
{
Tree[pos] += num;
pos += lowbit(pos);
}
} __int64 GetSum(int pos)
{
__int64 s=;
while(pos)
{
s += Tree[pos];
pos -= lowbit(pos);
}
return s;
} int main()
{
while(scanf("%d", &n), n)
{
met(a,); met(Tree, ); met(Hash, );
for(int i=; i<=n; i++)
{
scanf("%d", &a[i].V);
a[i].id = i;
} sort(a+, a+n+);///按V从大到小排序;
for(int i=; i<=n; i++)
Hash[a[i].id] = i;///离散化后的Hash数组大小关系顺序和输入的数组大小关系一样; __int64 ans=;
for(int i=; i<=n; i++)
{
int pos = Hash[i];
Update(pos, );///每插入一个数时,就把那个位置置为1;
int m = GetSum(pos);///从第一个元素到第pos个元素的和,即m=前pos个元素中小于pos的个数;
ans += i-m;///所以逆序数应该加上比pos个元素大的,即总个数-比pos小的;
}
printf("%I64d\n", ans);
}
return ;
}
树状数组
也可以用线段树来写,每次更新pos点,然后在求1-pos的和即可
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <queue>
#include <stack>
#include <algorithm>
#include <map>
#include <string>
typedef long long LL;
#define INF 0x3f3f3f3f
#define met(a, b) memset(a, b, sizeof(a))
#define N 500005 using namespace std; #define Lson r<<1
#define Rson r<<1|1 struct node
{
int L, R;
LL sum;
int Mid(){return (L+R)/;}
}a[N*]; struct Num
{
int num, pos;
friend bool operator < (Num p, Num q)
{
return p.num > q.num;
}
}b[N]; void Build(int r, int L, int R)
{
a[r].L = L; a[r].R = R; if(L == R) return; Build(Lson, L, a[r].Mid());
Build(Rson, a[r].Mid()+, R);
} void Update(int r, int pos, int num)
{
if(a[r].L == pos && a[r].R == pos)
{
a[r].sum += num;
return ;
} if(pos > a[r].Mid())
Update(Rson, pos, num);
else if(pos <= a[r].Mid())
Update(Lson, pos, num); a[r].sum = a[Lson].sum + a[Rson].sum;
} LL Query(int r, int L, int R)
{
if(L > R) return ; if(a[r].L == L && a[r].R == R)
return a[r].sum; if(R <= a[r].Mid())
return Query(Lson, L, R);
else if(L > a[r].Mid())
return Query(Rson, L, R);
else
{
LL ans1 = Query(Lson, L, a[r].Mid());
LL ans2 = Query(Rson, a[r].Mid()+, R);
return ans1 + ans2;
}
} int main()
{
int n;
while(scanf("%d", &n), n)
{
met(a, );
met(b, ); for(int i=; i<=n; i++)
{
scanf("%d", &b[i].num);
b[i].pos = i;
} Build(, , n); sort(b+, b+n+); LL ans = ;
for(int i=; i<=n; i++)
{
Update(, b[i].pos, );
ans += Query(, , b[i].pos-);
}
printf("%I64d\n", ans);
}
return ;
}
线段树
Ultra-QuickSort---poj2299 (归并排序.逆序数.树状数组.离散化)的更多相关文章
- POJ 2299 Ultra-QuickSort 逆序数 树状数组 归并排序 线段树
题目链接:http://poj.org/problem?id=2299 求逆序数的经典题,求逆序数可用树状数组,归并排序,线段树求解,本文给出树状数组,归并排序,线段树的解法. 归并排序: #incl ...
- ACM学习历程—HDU5592 ZYB's Premutation(逆序数 && 树状数组 && 二分)(BestCoder Round #65 1003)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5592 题目大意就是给了每个[1, i]区间逆序对的个数,要求复原原序列. 比赛的时候2B了一发. 首先 ...
- cdoj 841 休生伤杜景死惊开 逆序数/树状数组
休生伤杜景死惊开 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 陆伯言军陷八卦 ...
- P1908 逆序对——树状数组&离散化&快读快写の学习
题目简述: 对于给定的一段正整数序列,逆序对就是序列中 a_i>a_jai>aj 且 i<ji<j 的有序对. 输出序列中逆序对的数目. 知识补充: 树状数组: 这东西就是 ...
- hdu 1394 Minimum Inversion Number 逆序数/树状数组
Minimum Inversion Number Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showprob ...
- zoj 3157 Weapon 逆序数/树状数组
B - Weapon Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu Submit Sta ...
- [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)
[BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...
- POJ 2299 【树状数组 离散化】
题目链接:POJ 2299 Ultra-QuickSort Description In this problem, you have to analyze a particular sorting ...
- BZOJ_5055_膜法师_树状数组+离散化
BZOJ_5055_膜法师_树状数组+离散化 Description 在经历过1e9次大型战争后的宇宙中现在还剩下n个完美维度, 现在来自多元宇宙的膜法师,想偷取其中的三个维度为伟大的长者续秒, 显然 ...
随机推荐
- par函数bty参数-控制绘图边框
bty 可以看作box type 的缩写,控制绘图边框的显示,取值范围为o, l, u, c, ], n 默认值为"o", 代码示例: par(bty = "o" ...
- jQuery实现HTML表格单元格的合并功能
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- linux用户态定时器的使用---19
原创博文,转载请标明出处--周学伟http://www.cnblogs.com/zxouxuewei/ linux操作系统为每一个进程提供了3个内部计时器. ITIMER_REAL;ITIMER_VI ...
- ubuntu普通用户无法使用usdo命令
1.切换到root用户下,怎么切换就不用说了吧,不会的自己百度去. 2.添加sudo文件的写权限,命令是: chmod u+w /etc/sudoers 3.编辑sudoers文件 vi /etc/s ...
- swift学习笔记之---数组、字典、枚举、结构体
1.数组-Array let types = ["none","warning","error"] //省略类型的数组声明 let menb ...
- swift学习笔记之控制流
控制流: 1.if语句 let count = { print("yes") }else{ print("no") } 2.switch语句 (1)Swift中 ...
- ActiveMQ伪集群部署
本文借鉴http://www.cnblogs.com/guozhen/p/5984915.html,在此基础上进行了完善,使之成为一个完整版的伪分布式部署说明,在此记录一下! 一.本文目的 介绍如何在 ...
- android 仿QQ手机版
千人2群开启,欢迎大家围观打酱油,群号145667827 您当前位置 : JavaApk-安卓应用游戏源码服务专家 » QQ » Android项目源码界面超级华丽的仿QQ最新版本 Andro ...
- ubuntu下code::blocks编译运行一个简单的gtk+2.0项目
在具体的操作之前,首先需要安装一些必要的软件.ubuntu下默认安装了gcc,不过缺少必要的Header file,可以在命令行中输入下面的指令安装build-essential套件:sudo apt ...
- win8.1rtm专业版无法安装net3.5还有iis
win8.1rtm专业版无法安装net3.5还有iis错误代码:0x800F0906 已解决:dism.exe /online /enable-feature /featurename:NetFX3 ...