poj 2299 Ultra-QuickSort 二分+线段树求逆序数
2015-07-22 11:21
417 查看
Ultra-QuickSort
Description
In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is
sorted in ascending order. For the input sequence
9 1 0 5 4 ,
Ultra-QuickSort produces the output
0 1 4 5 9 .
Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.
Input
The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence
element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.
Output
For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.
Sample Input
Sample Output
题意:给出一个序列,可以交换任意两个数,最终使得序列从小到大排序,求最少交换次数。
思路:一个数要交换的次数就是看他前面有几个数比它大,也就是它的逆序数。最终就是求所有数的逆序数之和。但是看题目条件n最大有50000,若每个逆序数都循环一遍,就是n*n肯定超时了,得改进。一个思路就是,先将数列排序,对于原始数列中每一个数,二分找出它在排序之后的位置p,然后插入到线段树中对应位置,那么每个数的逆序数就是查询[p,n]中有多少个数。
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 500000+10
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int n;
int sum[maxn<<2];
int b[maxn];
int a[maxn];
void pushUp(int rt){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void build(int l,int r,int rt){
if(l==r){
sum[rt] = 0;
return;
}
int m = (l+r) >> 1;
build(lson);
build(rson);
pushUp(rt);
}
void update(int p,int l,int r,int rt){
if(l==r){
sum[rt] = 1;
return;
}
int m = (l+r) >>1;
if(p<=m) update(p,lson);
else update(p,rson);
pushUp(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l && r<=R) return sum[rt];
int m = (l+r) >> 1;
int res = 0;
if(L<=m) res += query(L,R,lson);
if(R>m) res += query(L,R,rson);
return res;
}
int main(){
while(~scanf("%d",&n) && n){
build(0,n-1,1);
for(int i=0;i<n;i++){
scanf("%d",&b[i]);
a[i] = b[i];
}
sort(b,b+n);
long long ans = 0;
for(int i=0;i<n;i++){
int p = a[i];
int l=0,r=n,m;
while(l<r){
m = (l+r) >> 1;
if(b[m] > p) r = m;
else l = m+1;
}
int temp = query(r-1,n-1,0,n-1,1);
//printf("@@@%d %d\n",r-1,temp);
ans += temp;
update(r-1,0,n-1,1);
}
printf("%lld\n",ans);
}
return 0;
}
Time Limit: 7000MS | Memory Limit: 65536K | |
Total Submissions: 47564 | Accepted: 17354 |
In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is
sorted in ascending order. For the input sequence
9 1 0 5 4 ,
Ultra-QuickSort produces the output
0 1 4 5 9 .
Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.
Input
The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence
element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.
Output
For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.
Sample Input
5 9 1 0 5 4 3 1 2 3 0
Sample Output
6 0
题意:给出一个序列,可以交换任意两个数,最终使得序列从小到大排序,求最少交换次数。
思路:一个数要交换的次数就是看他前面有几个数比它大,也就是它的逆序数。最终就是求所有数的逆序数之和。但是看题目条件n最大有50000,若每个逆序数都循环一遍,就是n*n肯定超时了,得改进。一个思路就是,先将数列排序,对于原始数列中每一个数,二分找出它在排序之后的位置p,然后插入到线段树中对应位置,那么每个数的逆序数就是查询[p,n]中有多少个数。
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 500000+10
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int n;
int sum[maxn<<2];
int b[maxn];
int a[maxn];
void pushUp(int rt){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void build(int l,int r,int rt){
if(l==r){
sum[rt] = 0;
return;
}
int m = (l+r) >> 1;
build(lson);
build(rson);
pushUp(rt);
}
void update(int p,int l,int r,int rt){
if(l==r){
sum[rt] = 1;
return;
}
int m = (l+r) >>1;
if(p<=m) update(p,lson);
else update(p,rson);
pushUp(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l && r<=R) return sum[rt];
int m = (l+r) >> 1;
int res = 0;
if(L<=m) res += query(L,R,lson);
if(R>m) res += query(L,R,rson);
return res;
}
int main(){
while(~scanf("%d",&n) && n){
build(0,n-1,1);
for(int i=0;i<n;i++){
scanf("%d",&b[i]);
a[i] = b[i];
}
sort(b,b+n);
long long ans = 0;
for(int i=0;i<n;i++){
int p = a[i];
int l=0,r=n,m;
while(l<r){
m = (l+r) >> 1;
if(b[m] > p) r = m;
else l = m+1;
}
int temp = query(r-1,n-1,0,n-1,1);
//printf("@@@%d %d\n",r-1,temp);
ans += temp;
update(r-1,0,n-1,1);
}
printf("%lld\n",ans);
}
return 0;
}
相关文章推荐
- hdu 5288 OO’s Sequence(2015 Multi-University Training Contest 1)
- 【UIKit】-4-UIActivityIndicatorView - 系统转菊花
- HDU 5288 OO’s Sequence (二分)2015多校训练一
- UIlabel添加背景图片
- NGUI UIScrollView卡顿,使用对象池性能优化
- LMON:terminating instance due to error 481
- ueditor 后端配置项没有正常加载,上传插件不能正常使用!jsp版本
- tair 分布式key/value存储系统 环境搭建
- 去掉UITableView中多余空行
- 2015多校第一场 hdu 5288 OO’s Sequence
- SPOJ 375 Query on a tree (树链剖分+线段树)
- Target runtime com.genuitec.runtime.generic.jee60 is not defined的解决方案
- What are the best practices for building something like a News Feed?
- UIViewAdditions(一个非常方便的工具类用它)
- 关于configure中build,target,host中的若干问题
- 【从零开始学NGUI 】 (二)Label
- UIView frame, bounds and center
- RMQ(Range Minimum/Maximum Query)问题——ST算法
- UESTC 360 Another LCIS(线段树区间更新)
- 【UIKit】-3-UIAccessibility - 元素可访问性,辅助功能