题意 : 给出一个数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. [转帖]2015年时的新闻:Debian GNU/Hurd 2015 发布

    Debian GNU/Hurd 2015 发布 oschina 发布于 2015年04月30日 https://www.oschina.net/news/62004/debian-gnu-hurd-2 ...

  2. Linux学习笔记(15)Linux字符集(locale,LANG,LC_ALL)

    关键词:linux系统修改编码,linux字符集问题, 目录  零.什么是locale 一.locale的详细内容 二.理解locale的设置 三 具体设定locale的方法(zh_CN.UTF-8. ...

  3. // TODO Auto-generated method stub 作用及设置

    当我们创建一个主方法类时,eclipse会默认插入一条注释语句: // TODO Auto-generated method stub 作用: // TODO Auto-generated metho ...

  4. Jave Web使用的设计模型

    Jave Web使用的设计模型 Mybatis 源码解读-设计模式总结 ImportNew 5月15日 (给ImportNew加星标,提高Java技能) 作者:crazyant www.crazyan ...

  5. 谈谈对this的指向问题

    普通函数中:this——window 定时器:this——window 构造函数中:this——当前实例化的对象 事件处理函数:this——事件触发对象

  6. LLVM 安装教程(包安装)

    LLVM 安装教程 环境:ubuntu16.04  llvm-4.0 clang-4.0 步骤: 1.依赖库安装 $ sudo apt-get install build-essential curl ...

  7. NLP采用Bert进行简单文本情感分类

    参照当Bert遇上Kerashttps://spaces.ac.cn/archives/6736此示例准确率达到95.5%+ https://github.com/CyberZHG/keras-ber ...

  8. 运行期优化 Java内存模型与线程 线程安全与优化

  9. 基于Chromium的浏览器已上线通用“显示密码”按钮

    基于Chromium的Edge在日前发布的Canary通道版本中,对用户界面进行了优化调整从而让InPrivate窗口变得更加简洁.在今天获得的版本更新中,微软继续带来了隐私相关的新内容--实现通用的 ...

  10. win10 安装ubuntu16.04双系统

    安装了两天的ubuntu系统,很是头疼,发现网上的内容,比较繁杂,因此,写此博客,进行综合整理,总结了安装方法.方便大家安装,减少搜索. 电脑是老师的电脑,配置为: 主板:微星 CPU:英特尔i5 7 ...