POJ 2299 Ultra-QuickSort (排序+数据离散化+求顺序数)
题意:给出一个序列,求至少需要用到多少次操作,才能将序列从小到大排序。
思路:
数据量很大,n<500000,所以用冒泡模拟是超时的。 接下来就想到了求顺序数,总共需要交换的次数为每个数后面有多少个小于它的数的累加和。 如9 1 0 5 4,9后面比它小的有4个,1后面比它小的有1个,5后面比它小的有1个,总共为6个,即为答案。 求顺序数自然而然就是想到用树状数组。
但是这里有一点,那就是整数是0~999999999,数据太大,开不了那么大的数组。 由于n最多只有500000,所以最多有50万个不同的数据,所以将数据离散化减少数据范围。
用结构体存储数据最初的值value,以及一开始所在的位置idx,还有就是离散后的值ranks。 之后按值排序,从小到大开始赋值,最小的赋值1,然后依次递增。如果前后两个值相同,那么后一个赋前一个的ranks值。 最后再按照一开始所在的位置排序,从后往前赋值给数组a,a[i]的顺序数是前i-1个数中比a[i]小的个数,然后求累加和。 (按原来顺序赋值也可以,这样是求位于a[i]后面比a[i]小的个数的累加和,求的时候for循环从n开始递减)。
注意最后输出要用long long!!!
797ms,时间比别人长很多。。。
(不知道为什么,该代码在UVA10810 同样的一道题,竟然是WA。。。)
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm> using namespace std;
const int maxn=;
int a[maxn+]; //存储离散后的数据序列,顺序是原来序列的顺序
int c[maxn+]; //树状数组求和
int n;
struct Node{
int idx,ranks; //一开始的位置,离散后的值
long long value; //最初的值
}node[maxn+];
//按value从小到大排序
bool cmp1(const Node & tmp1,const Node & tmp2){
return tmp1.value<tmp2.value;
}
//按idx从小到大排序
bool cmp2(const Node & tmp1,const Node & tmp2){
return tmp1.idx<tmp2.idx;
}
int lowbit(int x){
return x&(-x);
}
void update(int value,int i){
while(i<=n){
c[i]+=value;
i+=lowbit(i);
}
}
int sum(int i){
int sum=;
while(i){
sum+=c[i];
i-=lowbit(i);
}
return sum;
}
int main()
{
long long data;
while(scanf("%d",&n)!=EOF){
if(n==)
break;
memset(c,,sizeof(c));
for(int i=;i<n;i++){
scanf("%I64d",&data);
node[i].value=data;
node[i].idx=i;
}
sort(node,node+n,cmp1); //将数据离散化
int num=;
node[].ranks=;
for(int i=;i<n;i++){
if(node[i].value==node[i-].value){
node[i].ranks=node[i-].ranks;
}
else{
num++;
node[i].ranks=num;
}
}
sort(node,node+n,cmp2);
for(int i=;i<n;i++){
a[n-i]=node[i].ranks;
}
//求顺序数
long long ans=;
for(int i=;i<=n;i++){
ans+=sum(a[i]-);
update(,a[i]);
}
printf("%I64d\n",ans);
}
return ;
}
POJ 2299 Ultra-QuickSort (排序+数据离散化+求顺序数)的更多相关文章
- POJ 2299 Ultra-QuickSort (树状数组+离散化 求逆序数)
In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a seque ...
- POJ 2299 【树状数组 离散化】
题目链接:POJ 2299 Ultra-QuickSort Description In this problem, you have to analyze a particular sorting ...
- poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)
题目链接:http://poj.org/problem?id=2299 Description In this problem, you have to analyze a particular so ...
- poj 2299 Ultra-QuickSort(树状数组求逆序数)
链接:http://poj.org/problem?id=2299 题意:给出n个数,求将这n个数从小到大排序,求使用快排的需要交换的次数. 分析:由快排的性质很容易发现,只需要求每个数的逆序数累加起 ...
- POJ 2299 Ultra-QuickSort (树状数组 && 离散化&&逆序)
题意 : 给出一个数n(n<500,000), 再给出n个数的序列 a1.a2.....an每一个ai的范围是 0~999,999,999 要求出当通过相邻两项交换的方法进行升序排序时需要交换 ...
- POJ 1177 Picture(线段树 扫描线 离散化 求矩形并面积)
题目原网址:http://poj.org/problem?id=1177 题目中文翻译: 解题思路: 总体思路: 1.沿X轴离散化建树 2.按Y值从小到大排序平行与X轴的边,然后顺序处理 如果遇到矩形 ...
- POJ 2299 Ultra-QuickSort 归并排序、二叉排序树,求逆序数
题目链接: http://poj.org/problem?id=2299 题意就是求冒泡排序的交换次数,显然直接冒泡会超时,所以需要高效的方法求逆序数. 利用归并排序求解,内存和耗时都比较少, 但是有 ...
- POJ 2299 Ultra-QuickSort (树状数组 && 离散化)
题意 : 给出一个数n(n<500,000), 再给出n个数的序列 a1.a2.....an每一个ai的范围是 0~999,999,999 要求出当通过相邻两项交换的方法进行升序排序时需要交换 ...
- POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化)
POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化) 题意分析 前置技能 线段树求逆序对 离散化 线段树求逆序对已经说过了,具体方法请看这里 离散化 有些数 ...
随机推荐
- iPhone Tableview分批显示数据
//非原创 iPhone Tableview分批显示数据是本文要介绍的内容,主要讲解的是数据的显示.iPhone屏幕尺寸是有限的,如果需要显示的数据很多,可以先数据放到一个table中,先显示10 ...
- iOS Foundation框架 -3.利用NSNumber和NSValue将非OC对象类型数据存放到集合
1.Foundation框架中提供了很多的集合类如:NSArray,NSMutableArray,NSSet,NSMutableSet,NSDictionary,NSMutableDictionary ...
- mobileconfig文件的签名和认证(signed、verified)
专题:基于IOS上MDM技术相关资料整理及汇总mobileconfig文件的签名和认证(signed.verified) 一.功能描述: 鉴于我们的设备和MDM server之间已经可以通信,并能完成 ...
- HttpWebResponse取不到Cookie?原来是因为被跳转了
今天做模拟登陆的时候,发现HttpWebResponse的Cookie都为空,但是Fiddler看是有的...后来看见是302状态,才知道请求这个的时候,Response回来已经是跳转了...这样Co ...
- ARP协议详解
ARP协议:地址解析协议,将IP地址映射到MAC地址. ARP缓存:每个主机都有存储IP地址和MAC地址的缓冲区.每条记录最长生存时间为10分钟,如果一条记录2分钟没有使用,则会被删除.如果始终在使用 ...
- Ubuntu 12.04 修改默认启动为字符界面
sudo vim /etc/default/grub 修改GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" 为:GRUB_CMDLINE_LINU ...
- jqueryGrid 内置的onclickSubmit afterSubmit
$(document).ready(function() { $('#jpgCustomers').jqGrid({ //url from wich data should be requested ...
- Oracle中的for语句
for语句是一个可预置循环次数的循环控制语句,他是一个循环计数器,通常是一个整形变量,通过这个循环计数器来控制循环执行的次数 语法如下: for variable_counter_name in [e ...
- Linux 挂载2T以上存储
在生产环境中,我们会遇到分区大于2T的磁盘(比如:添加一个3TB的存储),由于MBR分区表只支持2T磁盘,所以大于2T的磁盘必须使用GPT分区表 而fdisk是不支持GPT分区的,我们可以使用part ...
- GGS: Sybase to Oracle
Step 1: Start the GGSCI on Source and Target Source Target Oracle GoldenGate Command Interpreter for ...