题意 : 给出一个数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. 2019牛客暑期多校训练营(第二场)-F artition problem

    题目链接:https://ac.nowcoder.com/acm/contest/882/F 题意:将2×n个人分成两组,每组n个人,求一个组中所有人和另外一组的所有人的竞争值之和. 思路: 比赛时看 ...

  2. 浅谈Linux kill命令

    傻瓜常规篇: 首先,用ps查看进程,方法如下: $ ps -ef ……smx       1822     1  0 11:38 ?        00:00:49 gnome-terminalsmx ...

  3. 索引及explain 详解

    索引的分类: 普通索引:仅加速查询 唯一索引:加速查询 + 列值唯一(可以有null) 主键索引:加速查询 + 列值唯一(不可以有null)+ 表中只有一个 组合索引:多列值组成一个索引,专门用于组合 ...

  4. 四则运算计算器的微信小程序_2 运算

    js文件: function isOperator(value) {   var operatorString = '+-*/()×÷';   return operatorString.indexO ...

  5. reids集群状态正常redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachable node in cluster

    重新启动redis集群时启动失败,报错: redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachab ...

  6. SQL之事务

    ●事务的ACID(acid)属性 ➢1.原子性(Atomicity ) 原子性是指事务是-一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生. ➢2. 一致性(Consistency) 事务 ...

  7. c++学习笔记之类和对象(三、static静态成员变量和静态成员函数)

    一.static静态成员变量 对象的内存中包含了成员变量,不同的对象占用不同的内存,这使得不同对象的成员变量相互独立,它们的值不受其他对象的影响.是有时候我们希望在多个对象之间共享数据,对象 a 改变 ...

  8. Tensorflow常见函数case argmax equal

    常用的函数: tf.argmax(input, axis=None, name=None, dimension=None) input:输入Tensor axis:0表示按列,1表示按行 name:名 ...

  9. SQL学习(二)之四大查询语句以及标准写法

    SQL四大查询语句——增删改查 增-INSERT INSERT INTO 表 (字段列表) VALUES(值列表) INSERT INTO `user_table` (`ID`, `username` ...

  10. 108、如何使用 Secret? (Swarm15)

    参考https://www.cnblogs.com/CloudMan6/p/8068057.html   我们经常要想容器传递敏感信息,最常见的就是密码.比如:   docker run -e MYS ...