poj2299Ultra-QuickSort【线段树求逆序数】离散化
2016-03-15 16:48
531 查看
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
Source
Waterloo local 2005.02.05
之前写过求逆序数的树状数组的方法和归并排序的方法
poj2299Ultra-QuickSort【树状数组求逆序数、离散化】、【归并排序模板】
感觉逆序数这玩意就应该用归并排序做啊~~
说线段树的方法:与上一篇
poj2352Stars【线段树单点更新区间求和】
相似的是,都是单点更新区间求和,而且从自身到根节点这一路一直++。不同的是,之前那个题是求前一部分的和,这个要求后一部分的值,这我就不理解了,逆序数明明等于N-[1,i]的值啊,为啥查询的时候只需要求[i+1,n]?好好想想:区间[1,i]的值+区间[i+1,N]的值=区间[1,N]的值(i已经标记为1),所以区间[i+1,N]值的总和等于N-[1,i]的值!因为总共有N个数,不是比它小就是比它(大或等于)。……
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 500005
struct node
{
int id,val;
}num[maxn];
bool cmp(node n1,node n2)
{
return n1.val<n2.val;
}
struct Tree
{
int l,r,tot;
}tree[maxn<<2];
int rank[maxn];
void build(int rt,int l,int r)
{
tree[rt].l=l;tree[rt].r=r;
tree[rt].tot=0;
if(l==r)return;
int mid=(l+r)/2;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
void update(int rt,int x)
{
tree[rt].tot++;
if(tree[rt].l==tree[rt].r&&tree[rt].l==x)
return;
int mid=(tree[rt].l+tree[rt].r)/2;
if(x<=mid)update(rt<<1,x);
else update(rt<<1|1,x);
}
int query(int rt,int l,int r)
{
int sum=0;
if(tree[rt].l==l&&tree[rt].r==r)
return tree[rt].tot;
int mid=(tree[rt].l+tree[rt].r)/2;
if(r<=mid) sum=query(rt<<1,l,r);
else if(l>mid) sum=query(rt<<1|1,l,r);
else
sum=query(rt<<1,l,mid)+query(rt<<1|1,mid+1,r);
return sum;
}
int main()
{
// freopen("cin.txt","r",stdin);
int n;
while(~scanf("%d",&n)&&n)
{
for(int i=0;i<n;i++)
{
scanf("%d",&num[i].val);
num[i].id=i;
}
sort(num,num+n,cmp);
for(int i=0;i<n;i++) rank[num[i].id]=i+1;
build(1,0,n+1);
long long sum=0;
for(int i=0;i<n;i++)
{
int x = rank[i];
sum+=query(1,x+1,n+1);
update(1,x);
}
printf("%I64d\n",sum);
}
return 0;
}
Time Limit: 7000MS | Memory Limit: 65536K | |
Total Submissions: 52097 | Accepted: 19113 |
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
Source
Waterloo local 2005.02.05
之前写过求逆序数的树状数组的方法和归并排序的方法
poj2299Ultra-QuickSort【树状数组求逆序数、离散化】、【归并排序模板】
感觉逆序数这玩意就应该用归并排序做啊~~说线段树的方法:与上一篇
poj2352Stars【线段树单点更新区间求和】
相似的是,都是单点更新区间求和,而且从自身到根节点这一路一直++。不同的是,之前那个题是求前一部分的和,这个要求后一部分的值,这我就不理解了,逆序数明明等于N-[1,i]的值啊,为啥查询的时候只需要求[i+1,n]?好好想想:区间[1,i]的值+区间[i+1,N]的值=区间[1,N]的值(i已经标记为1),所以区间[i+1,N]值的总和等于N-[1,i]的值!因为总共有N个数,不是比它小就是比它(大或等于)。……#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 500005
struct node
{
int id,val;
}num[maxn];
bool cmp(node n1,node n2)
{
return n1.val<n2.val;
}
struct Tree
{
int l,r,tot;
}tree[maxn<<2];
int rank[maxn];
void build(int rt,int l,int r)
{
tree[rt].l=l;tree[rt].r=r;
tree[rt].tot=0;
if(l==r)return;
int mid=(l+r)/2;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
void update(int rt,int x)
{
tree[rt].tot++;
if(tree[rt].l==tree[rt].r&&tree[rt].l==x)
return;
int mid=(tree[rt].l+tree[rt].r)/2;
if(x<=mid)update(rt<<1,x);
else update(rt<<1|1,x);
}
int query(int rt,int l,int r)
{
int sum=0;
if(tree[rt].l==l&&tree[rt].r==r)
return tree[rt].tot;
int mid=(tree[rt].l+tree[rt].r)/2;
if(r<=mid) sum=query(rt<<1,l,r);
else if(l>mid) sum=query(rt<<1|1,l,r);
else
sum=query(rt<<1,l,mid)+query(rt<<1|1,mid+1,r);
return sum;
}
int main()
{
// freopen("cin.txt","r",stdin);
int n;
while(~scanf("%d",&n)&&n)
{
for(int i=0;i<n;i++)
{
scanf("%d",&num[i].val);
num[i].id=i;
}
sort(num,num+n,cmp);
for(int i=0;i<n;i++) rank[num[i].id]=i+1;
build(1,0,n+1);
long long sum=0;
for(int i=0;i<n;i++)
{
int x = rank[i];
sum+=query(1,x+1,n+1);
update(1,x);
}
printf("%I64d\n",sum);
}
return 0;
}
相关文章推荐
- finish with non-zero exit value 42
- jmeter 性能测试 JDBC Request (查询数据库获取数据库数据) 的使用
- 教你如何用PS制作多款按钮UI设计教程
- OCiOS开发:UIKit 力学(UIDynamics)(二)
- iOS用xib文件创建UITableView
- iOS Controller 瘦身运动之 UItableView datasource 与 delegate的分离
- leetcode:Unique Paths II
- EasyUI加载树控件自动展开所有目录
- requireJS 简单上手
- easyui reload方法报Cannot read property 'options' of undefined
- RecyclerView_QuickAdapter及相关封装简化
- STL中vector、list、deque和map的区别
- oc--UINavigationController控制器
- quick 3.3 按钮多次点击出现问题的解决
- Android UI-仿微信底部导航栏布局
- String、StringBuffer和StringBuilder的区别
- HD2767Proving Equivalences(有向图强连通分量+缩点)
- android opencv build.gradle
- leetcode:N-Queens II 【Java】
- Android requires compiler compliance level 5.0 or 6.0. Found '1.4' instead