题意 : 给出一个数n(n<500,000), 再给出n个数的序列 a1、a2.....an每一个ai的范围是 0~999,999,999  要求出当通过相邻两项交换的方法进行升序排序时需要交换的次数

分析 : 经典题目, 只要求出这堆乱序序列里面有多少个逆序对即可, 但是数据量很大, 单纯的循环暴力求法肯定是超时的! 利用树状数组可以高效求解, 代码如下, 建议先百度了解一下

;
; i<=n; i++){
    ans += i - sum(a[i]);//i为已近插入的点的个数
    add(a[i], );//单点更新+1操作
}

但是, 这道题有个非常棘手的问题, 那就是每一个ai点的最大可能取值很大,  而树状数组的下标正是来存储这些点的, 很显然数组不可能开那么大,  即对于这题来讲有些数据本身很大, 自身无法作为数组的下标保存对应的属性。但是如果这时只是需要这堆数据的相对属性, 那么可以对其进行离散化处理!

离散化:当数据只与它们之间的相对大小有关,而与具体是多少无关时,可以进行离散化。

因为题目解法只关心个个元素的大小关系, 所以可以采用离散化来优化, 核心也就是在相对大小关系不变的情况下将本来很大的数变成很小的数, 这样就能存进树状数组中进行操作了!

下面针对这道题说明如何进行离散化, 首先举个例子来说明离散化前和离散化后元素都变成了什么样子, 以n = 4为例, Order为给出顺序, val为给出的原始值, new val为离散化后的值

Order            a1          a2      a3      a4

val            9999999    25      100   10000

new val         4            1        2        3

这样变化的话就能将数压到很小, 最大也不过是n的最大取值500000, 作为数组下标来说完全可以接受!下面说做法 :

1、用一个定义了两个整形变量ord和val的结构体数组arr存储原始输入元素的输入顺序和元素的值。

2、再根据结构体val的值进行升序排序, 于是将结构题里面的ord也进行了重排。

3、刚刚说到要刷新的是val, 于是再定义一个数组MAP将1到n的值作为new val去重新刷新val, 具体就是for(int i=1; i<=n; i++) MAP[arr[i].ord] = i;

值得注意的是, 在进行离散化的时候, 高清各个变量和下表等参加离散化操作的关系, 理清楚之后再进行编码, 否则很容易搞混或者搞乱!刚刚上面的循环我就写成了

for(int i=1; i<=n; i++) MAP[i] = arr[i].ord;    然后纳闷了好久为何WA  =_=

#include<stdio.h>
#include<string.h>
#include<string>
#include<map>
#include<set>
#include<algorithm>
#include<iostream>
#include<sstream>
#include<list>
#include<vector>
#include<queue>
#define lowbit(i) (i&(-i))
using namespace std;
;
int c[maxn];
typedef struct ARRAY{
    int ord, val;
}A;
A arr[maxn];
int MAP[maxn];
inline void add(int i, int val)
{
    ){
        c[i] += val;
        i += lowbit(i);
    }
}
inline int sum(int i)
{
    ;
    ){
        sum += c[i];
        i -= lowbit(i);
    }
    return sum;
}
bool cmp(const A fir, const A sec)
{
    return fir.val < sec.val;
}
int main(void)
{
    int n;
    while(~scanf("%d", &n) && n){
        memset(c, , sizeof(c));
        ; i<n; i++){
            scanf("%d", &arr[i].val);
            arr[i].ord = i;
        }
        sort(arr, arr+n, cmp);
        ; i<n; i++){
            MAP[arr[i].ord] = i;
        }
        ;
        ; i<n; i++){
            cnt += i - sum(MAP[i]+);
            add(MAP[i]+, );
        }
        printf("%lld\n", cnt);
    }
    ;
}

POJ 2299 Ultra-QuickSort (树状数组 && 离散化)的更多相关文章

  1. POJ 2299 Ultra-QuickSort(树状数组+离散化)

    http://poj.org/problem?id=2299 题意:给出一组数,求逆序对. 思路: 这道题可以用树状数组解决,但是在此之前,需要对数据进行一下预处理. 这道题目的数据可以大到999,9 ...

  2. POJ - 2299 Ultra-QuickSort 【树状数组+离散化】

    题目链接 http://poj.org/problem?id=2299 题意 给出一个序列 求出 这个序列要排成有序序列 至少要经过多少次交换 思路 求逆序对的过程 但是因为数据范围比较大 到 999 ...

  3. poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)

    题目链接:http://poj.org/problem?id=2299 Description In this problem, you have to analyze a particular so ...

  4. poj 2299 Ultra-QuickSort(树状数组求逆序数)

    链接:http://poj.org/problem?id=2299 题意:给出n个数,求将这n个数从小到大排序,求使用快排的需要交换的次数. 分析:由快排的性质很容易发现,只需要求每个数的逆序数累加起 ...

  5. poj 2299 Ultra-QuickSort(树状数组)

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 67681   Accepted: 25345 ...

  6. POJ 2299 Ultra-QuickSort【树状数组 ,逆序数】

    题意:给出一组数,然后求它的逆序数 先把这组数离散化,大概就是编上号的意思--- 然后利用树状数组求出每个数前面有多少个数比它小,再通过这个数的位置,就可以求出前面有多少个数比它大了 这一篇讲得很详细 ...

  7. POJ 2299 【树状数组 离散化】

    题目链接:POJ 2299 Ultra-QuickSort Description In this problem, you have to analyze a particular sorting ...

  8. hdu4605 树状数组+离散化+dfs

    Magic Ball Game Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  9. BZOJ_5055_膜法师_树状数组+离散化

    BZOJ_5055_膜法师_树状数组+离散化 Description 在经历过1e9次大型战争后的宇宙中现在还剩下n个完美维度, 现在来自多元宇宙的膜法师,想偷取其中的三个维度为伟大的长者续秒, 显然 ...

  10. POJ 2299 树状数组+离散化求逆序对

    给出一个序列 相邻的两个数可以进行交换 问最少交换多少次可以让他变成递增序列 每个数都是独一无二的 其实就是问冒泡往后 最多多少次 但是按普通冒泡记录次数一定会超时 冒泡记录次数的本质是每个数的逆序数 ...

随机推荐

  1. 【Linux-驱动】printk的打印级别

    级别: 日志级别用宏表示,日志级别宏展开为一个字符串,在编译是由预处理器将它和消息本文拼接成一个字符串,因此printk函数中日志级别宏和格式字符串间不能有逗号.printk的日志级别定义在 /inc ...

  2. Oacle常用语句

    1.建表语句 ) NOT NULL, region_id ) NOT NULL, salesperson_id ) NOT NULL, ) NOT NULL, ) NOT NULL, tot_orde ...

  3. sublime text3 注册码 (Version 3.0)

    -– BEGIN LICENSE -– TwitterInc 200 User License EA7E-890007 1D77F72E 390CDD93 4DCBA022 FAF60790 61AA ...

  4. 掌握MyBatis的核心对象

    一.获取SqlSessionFactoryBuilder对象 1.SqlSessionFactoryBuilder的作用 所有的MyBatis应用都是以SqlSessionFactory实例为中心.S ...

  5. 快速部署单节点RancherServer

    已安装 docker,并配置docker国内镜像源 docker version docker pull rancher/rancher:v2.2.0 docker run -d -p 80:80 - ...

  6. 进程之multiprocessing模块代码篇

    这里再把之前的内容总结和补充一下: 并发和并行: 你在干坏事,来了一个电话,干完坏事再去接电话,说明你既不是并发也不是并行. 你在干坏事,来了一个电话,你接完电话接着干坏事,说明你支持并发 你在干坏事 ...

  7. 配置Mysql远程连接

    一.赋予某个用户权限 1.赋予权限格式:grant 权限 on 数据库对象 to 用户@IP(或者相应正则) 注:可以赋予select,delete,update,insert,index等权限精确到 ...

  8. 深入理解hadoop之机架感知

    深入理解hadoop之机架感知 机架感知 hadoop的replication为3,机架感知的策略为: 第一个block副本放在和client所在的datanode里(如果client不在集群范围内, ...

  9. js的作用主要这么几个

    js的作用主要有这么几个表单验证:网页上,用户输入的信息需要进行验证,在客户端验证,可以减少对服务器端的压力.所以,你应该把握正则表达式方面的知识.网页特效:页面上很多特效是非常好的,能产生很好的用户 ...

  10. Excel中的常用快捷键

    1)工作表之间快速切换 Ctrl+PageUp切换的是当前所在工作表的前一个工作表, Ctrl+PageDown切换的是当前所在工作表的后一个工作表. 2)Ctrl +Home 强迫回到最前一个单元格 ...