题意 : 给出一个数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. PostgreSQL unlogged表

    PostgreSQL有一种介于正常表和临时表之间的类型表,称之为unlogged表,在该表新建的索引也属于unlogged,该表在写入数据时候并不将数据写入到持久的write-ahead log文件中 ...

  2. Python 列表(List)

    列表是最常用的Python数据类型,它可以作为一个方括号内的逗号分隔值出现. 列表的数据项不需要具有相同的类型. 一.列表定义 用逗号分隔不同的数据项使用方括号括起来. >>> li ...

  3. C++学习 之 继承(笔记)

    1.继承基础: 继承就像是生物里的遗传与变异,即派生类(子代)从基类(父代)那里继承基类的某些特性(遗传),并在此基础上拥有自己的特性(变异). C++派生语法: class Base//定义一个基类 ...

  4. GitHub从小白到熟悉<四>

    GitHub issue 使用教程 创建 一个issue  (显示所有bug 或者 说 交流的 问题列表)

  5. six库 解决python2的项目如何能够完全迁移到python3

    six库 解决python2的项目如何能够完全迁移到python3 SIX是用于python2与python3兼容的库. 它存在的目的是为了拥有无需修改即可在Python 2和Python 3上同时工 ...

  6. Codeforces 1178C. Tiles

    传送门 考虑一块块填,首先 $(1,1)$ 有 $4$ 种方案 然后根据 $(1,1)$ 的右边颜色,$(1,2)$ 有两种方案,$(1,3)$ 根据 $(1,2)$ 也有两种方案... 考虑 $(2 ...

  7. sql server truncate语句

    truncate语句 --truncate table '表名' --这样就利用SQL语句清空了该数据表,而不保留日志

  8. 重学HTML5的语义化

    干了这么多年的前端,之前面试的时候经常会遇到面试官提问:你是如何理解HTML的语义化的? 说实话,之前遇到这个问题的时候,都是从网上找参考答案,然后记下来,用自己的语言重新组织一下,就变成自己的理解了 ...

  9. js 格式化 json 字符串

    1.JSON.stringify的三个参数 var json = {"@odata.context":"$metadata#AddTableOne_466281s&quo ...

  10. dedecms 调用内容页分页

    arc.archives.class.php $TRUEfilename = $this->GetTruePath().$fileFirst."_".$i.".&q ...