AcWing 107. 超快速排序(归并排序 + 逆序对 or 树状数组)
在这个问题中,您必须分析特定的排序算法----超快速排序。
该算法通过交换两个相邻的序列元素来处理n个不同整数的序列,直到序列按升序排序。
对于输入序列9 1 0 5 4,超快速排序生成输出0 1 4 5 9。
您的任务是确定超快速排序需要执行多少交换操作才能对给定的输入序列进行排序。
输入格式
输入包括一些测试用例。
每个测试用例的第一行输入整数n,代表该用例中输入序列的长度。
接下来n行每行输入一个整数aiai,代表用例中输入序列的具体数据,第i行的数据代表序列中第i个数。
当输入用例中包含的输入序列长度为0时,输入终止,该序列无需处理。
输出格式
对于每个需要处理的输入序列,输出一个整数op,代表对给定输入序列进行排序所需的最小交换操作数,每个整数占一行。
数据范围
0≤N<5000000≤N<500000,
0≤ai≤9999999990≤ai≤999999999
输入样例:
5
9
1
0
5
4
3
1
2
3
0
输出样例:
6
0
算法:归并排序 + 逆序对 or 树状数组
题解:求最少的交换次数,其实就是求当前这个序列的逆序数。
归并排序 + 逆序对:
#include <iostream>
#include <cstdio> using namespace std; typedef long long ll; const int maxn = 5e5+; ll arr[maxn], b[maxn];
ll ans; void merge_sort(ll *arr, int l, int mid, int r) {
int i = l, j = mid + ;
int k = ;
while(i <= mid || j <= r) {
if(j > r || (i <= mid && arr[i] <= arr[j])) {
b[k++] = arr[i++];
} else {
ans += mid - i + ;
b[k++] = arr[j++];
}
}
for(int i = ; i < k; i++) {
arr[l + i] = b[i];
}
} void merge(ll *arr, int l, int r) {
if(l < r) {
int mid = (l + r) >> ;
merge(arr, l, mid);
merge(arr, mid + , r);
merge_sort(arr, l, mid, r);
}
} int main() {
int n;
while(scanf("%d", &n) && n) {
for(int i = ; i <= n; i++) {
scanf("%lld", &arr[i]);
}
ans = ;
merge(arr, , n);
cout << ans << endl;
}
return ;
}
树状数组:
#include <iostream>
#include <cstdio>
#include <memory.h>
#include <vector>
#include <algorithm> using namespace std; typedef long long ll; const int maxn = 5e5+; vector<int> v; int arr[maxn];
ll tree[maxn << ];
int size; int lowbit(int x) {
return x & (-x);
} int find(int x) {
return lower_bound(v.begin(), v.end(), x) - v.begin() + ;
} void update(int x, int val) {
while(x <= size) {
tree[x] += val;
x += lowbit(x);
}
} ll getSum(int x) { //求出前面有多少个小于或等于x的数
ll res = ;
while(x > ) {
res += tree[x];
x -= lowbit(x);
}
return res;
} int main() {
int n;
while(scanf("%d", &n) && n) {
memset(tree, , sizeof tree);
for(int i = ; i <= n; i++) {
scanf("%d", &arr[i]);
v.push_back(arr[i]);
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
size = v.size();
ll ans = ;
for(int i = ; i <= n; i++) {
update(find(arr[i]), );
ans += i - getSum(find(arr[i])); //用总数减去小于或等于arr[i]的数,就是当前这个数的逆序数
}
cout << ans << endl;
}
return ;
}
AcWing 107. 超快速排序(归并排序 + 逆序对 or 树状数组)的更多相关文章
- Day2:T4求逆序对(树状数组+归并排序)
T4: 求逆序对 A[I]为前缀和 推导 (A[J]-A[I])/(J-I)>=M A[j]-A[I]>=M(J-I) A[J]-M*J>=A[I]-M*I 设B[]=A[]-M*( ...
- hdu 4911 求逆序对数+树状数组
http://acm.hdu.edu.cn/showproblem.php?pid=4911 给定一个序列,有k次机会交换相邻两个位置的数,问说最后序列的逆序对数最少为多少. 实际上每交换一次能且只能 ...
- 【BZOJ 3295】动态逆序对 - 分块+树状数组
题目描述 给定一个1~n的序列,然后m次删除元素,每次删除之前询问逆序对的个数. 分析:分块+树状数组 (PS:本题的CDQ分治解法见下一篇) 首先将序列分成T块,每一块开一个树状数组,并且先把最初的 ...
- Bzoj 3295: [Cqoi2011]动态逆序对 分块,树状数组,逆序对
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2886 Solved: 924[Submit][Stat ...
- bzoj1831 逆序对 (dp+树状数组)
注意到,所有的-1应该是一个不降的序列,否则不会更优那就先求出来不是-1的的逆序对个数,然后设f[i][j]表示第i个-1放成j的前i个-1带来的最小逆序对数量这个可以树状数组来求 #include& ...
- P3157 [CQOI2011]动态逆序对(树状数组套线段树)
P3157 [CQOI2011]动态逆序对 树状数组套线段树 静态逆序对咋做?树状数组(别管归并QWQ) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...
- POJ2299逆序对模板(树状数组)
题目:http://poj.org/problem?id=2299 只能相邻两个交换,所以交换一次只会减少一个逆序对.所以交换次数就是逆序对数. ps:原来树状数组还可以记录后边lowbit位的部分和 ...
- 【Luogu】P3157动态逆序对(树状数组套主席树)
题目链接 md第一道在NOILinux 下用vim做的紫题.由于我对这个操作系统不是很熟悉,似乎有什么地方搞错了,md调死.(我还打了两遍代码,调了两个小时) 但是这道题并不难,就是树状数组套上主席树 ...
- BZOJ3295 动态逆序对(树状数组套线段树)
[Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 6058 Solved: 2117[Submit][Status][D ...
随机推荐
- Java 错误:Constructor call must be the first statement in a constructor
今天用学校里的黑马程序员通Java语法 想到了:在有参构造函数中调用无参构造函数 语法是这样的: class Person{ private int age; public Person() { Sy ...
- golang(4):函数 & 数组 & 切片 & map & 锁
内置函数 // 1. close:主要用来关闭channel // 2. len:用来求长度,比如string.array.slice.map.channel // 3. new:用来分配内存,主要用 ...
- luogu P5504 [JSOI2011]柠檬
bgm(雾) luogu 首先是那个区间的价值比较奇怪,如果推导后可以发现只有左右端点元素都是同一种\(s_x\)的区间才有可能贡献答案,并且价值为\(s_x(cnt(x)_r-cnt(x)_{l-1 ...
- iview表单验证之正则验证、函数验证
iview表单验证之正则 正则验证: 代码: loginRules: { stringLength: [ { required: true, message: '该字段不能为空', trigger: ...
- 帝国cms 描述和关键词动态获取
之前列表页首页和内容页调用的关键词和描述的字段不一样,所以说需要写好几套模板. 下边这个判断就不用像之前做几套模板了,通过判断获取不一样的字段. $GLOBALS[navinfor] 这个判断的是此页 ...
- C语言typedef详解
原文链接 C语言允许用户使用 typedef 关键字来定义自己习惯的数据类型名称,来替代系统默认的基本类型名称.数组类型名称.指针类型名称与用户自定义的结构型名称.共用型名称.枚举型名称等.一旦用户在 ...
- hive各种报错
搭建了 CDH6.1.0环境 新加入一台机器都hive但是报错 javax.jdo.JDODataStoreException: Required table missing : "`VER ...
- Redis主从配置以及哨兵模式
Redis主从模式,应用写master,读slave,减轻master的压力. 配置主结点: daemonize yes port 6379bind 0.0.0.0 pidfile /opt/redi ...
- 本地安装Mysql后,navicat链接异常:Clinet dose not support authentication protocol request by server ; consider upgrading MySQL client
第一步:首先通过cmd进入mysql 在命令窗口 输入:mysql -u root -p: 第二步:更改加密方式 mysql> ALTER USER 'root'@'localhost' IDE ...
- shell条件嵌套(if条件语句)
[注意1]:和Java.PHP等语言不一样,sh的流程控制不可为空,如: 代码如下: <?php if (isset($_GET["q"])) { search(q); } ...