Description

In this problem, you have to analyze a particular sorting algorithm. The
algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence 

9 1 0 5 4 ,


Ultra-QuickSort produces the output 

0 1 4 5 9 .


Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.

Input

The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence
element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.

Output

For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input
sequence.

本题的大意是求逆序对吧,只是有多组数据。大伙儿肯定习惯了归并排序;不过,我今天就是要强调的是树状数组。



---------------------------------------------我是分割线-----------------------------------------------



树状树的推导:

假设数组a[1..n],那么查询a[1]+...+a[n]的时间是log级别的,而且是一个在线的数据结构,支持随时修改某个元素的值,复杂度也为log级别。
来观察这个图:

树状数组的结构图

令这棵树的结点编号为C1,C2...Cn。令每个结点的值为这棵树的值的总和,那么容易发现:
C1 = A1
C2 = A1 + A2
C3 = A3
C4 = A1 + A2 + A3 + A4
C5 = A5
C6 = A5 + A6
C7 = A7
C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8
...
C16 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 + A16
这里有一个有趣的性质:
设节点编号为x,那么这个节点管辖的区间为2^k(其中k为x二进制末尾0的个数)个元素。因为这个区间最后一个元素必然为Ax,
所以很明显:Cn = A(n – 2^k + 1) + ... + An

预备代码:

lowbit:快速求与该数相关的之前的数.

add(或change):把x位置的值加上d(当然,其实为改变之后的值)

sum:求1-x的和。

(详细代码见下)



---------------------------------------------我是分割线-----------------------------------------------



思路:数据小的时候,我们开一个数组cnt,其范围是一组数中的最大值。cnt[i]表示数字i出现的次数(一开始清零)

我们从头操作,设每次取出的数为x,则它产生的逆序对(以它为较小者的逆序对)就是所有在此之前的比他大的数的个数。

究竟怎么表示呢? 借鉴于前缀和,我们可以用sum(tot)(tot是最大值)-sum(x-1),这就是目前记录的比它大的数(既然已经记录过,它们一定在x的前面。然而,数据范围有很多9,我们得另想办法。观察n<=50万,我们可以把n个数映射到最多为n的数组里再进行处理。别忘了去重。



代码:

#include<stdio.h>
#include<algorithm>
using namespace std;
struct arr{long x,y;}a[500001];
long cnt[500001],tot,n,i;
long long ans;
long lowbit(long x) {return x&(-x);}
void add(long x,long d)
{
  while (x<=n){cnt[x]+=d;x+=lowbit(x);}
}
long sum(long x)
{
  long ans=0;
  while (x>0){ans+=cnt[x];x-=lowbit(x);}
  return ans;
}
bool cmp(arr a,arr b){return (a.x<b.x);}
int main()
{
  scanf("%ld",&n);
  while (n>0)
  {
    ans=0;
    for (i=1;i<=n;i++)
      {
        scanf("%ld",&a[i].x);
      if (a[i].x==a[i-1].x) a[i].y=a[i-1].y;else a[i].y=a[i-1].y+1;//a[i].x记录数据,a[i].y作为映射,在排序里排进去。
      }
    tot=a[n].y;                                                                     //tot为数组个数,开始为最大值。
    sort(a+1,a+n+1,cmp);
    for (i=1;i<=tot;i++) cnt[i]=0;                                                //清零
    for (i=1;i<=n;i++)
    {
      ans+=sum(tot)-sum(a[i].y-1);                                            //加上当前数产生的逆序对。
      add(a[i].y,1);                                                                    //修改cnt
    }
    printf("%lld\n",ans);
    scanf("%ld",&n);
  }
  return 0;
}

poj 2299 Ultra-QuickSort 题解的更多相关文章

  1. POJ 2299 Ultra-QuickSort 简单题解

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 68874   Accepted: 25813 ...

  2. POJ 2823 Sliding Window 题解

    POJ 2823 Sliding  Window 题解 Description An array of size n ≤ 106 is given to you. There is a sliding ...

  3. 逆序数 POJ 2299 Ultra-QuickSort

    题目传送门 /* 题意:就是要求冒泡排序的交换次数. 逆序数:在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序. 一个排列中逆序的总数就称为这个排列的逆 ...

  4. 树状数组求逆序对:POJ 2299、3067

    前几天开始看树状数组了,然后开始找题来刷. 首先是 POJ 2299 Ultra-QuickSort: http://poj.org/problem?id=2299 这题是指给你一个无序序列,只能交换 ...

  5. POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化)

    POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化) 题意分析 前置技能 线段树求逆序对 离散化 线段树求逆序对已经说过了,具体方法请看这里 离散化 有些数 ...

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

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

  7. POJ 2299 Ultra-QuickSort(线段树+离散化)

    题目地址:POJ 2299 这题以前用归并排序做过.线段树加上离散化也能够做.一般线段树的话会超时. 这题的数字最大到10^10次方,显然太大,可是能够利用下标,下标总共仅仅有50w.能够从数字大的開 ...

  8. 题解报告:poj 2299 Ultra-QuickSort(BIT求逆序数)

    Description In this problem, you have to analyze a particular sorting algorithm. The algorithm proce ...

  9. poj 2299 逆序数

    http://poj.org/problem?id=2299 坑:答案是long long 输出……!!!!! 题意是:求一个数组进行冒泡排序交换的次数 题解:求逆序数 题解Ⅰ: 归并排序求逆序数 归 ...

随机推荐

  1. LR11关联问题

    LR11关联问题       最近,我在录制一份脚本在回放的时候报错,错误图如下: 很自然地我想到了关联,于是我再录制了一份脚本.我对比了一下ActionID=45322984确实是两个脚本不一样的地 ...

  2. 基于TypeScript的FineUIMvc组件式开发(概述)

    WebForm与Mvc 我简单说一下WebForm与Mvc,WebForm是微软很早就推出的一种WEB开发架构,微软对其进行了大量的封装,使开发人员可以像开发桌面程序一样去开发WEB程序,虽然开发效率 ...

  3. SpringMVC中使用RedirectAttributes重定向传参,防止暴露参数

    RedirectAttributes是SpringMVC3.1版本之后出来的一个功能,专门用于重定向之后还能带参数跳转的. 当我从jsp页面函数中带参数到controller层方法,方法执行完毕后返回 ...

  4. openfire muc 移除成员

    muc添加成员到数据库可参考 将Openfire中的MUC改造成类似QQ群一样的永久群 插件 插件是一位大神参考第一篇文章改进后编写的插件,进测试可以直接使用. ------------------- ...

  5. kafka 0.10.2 消息生产者

    package cn.xiaojf.kafka.producer; import org.apache.kafka.clients.producer.KafkaProducer; import org ...

  6. SDN学习之实现环路通信

    在对OpenFlow协议有了一定了解以后,开始尝试如何通过Ryu控制器实现网络中的通信.根据协议,我们知道,当数据信息首次传输到交换机时,由于交换机不存在该数据信息所对应的流表,因此,会触发Packe ...

  7. day_ha配置文件

    流程图: 代码 #!/sur/bin/env python # -*- coding: utf-8 -*- #{"backend": "www.oldboy.org&qu ...

  8. Android布局方式

    1. LinearLayout(线性布局)     android:orientation="vertical"    android:layout_width="wra ...

  9. Windows server 2008 r2 开启Aero

    1.右键“计算机”----“管理”----“添加功能”,选上“桌面体验”,一般来说要把服务器系统做成工作 站的话,最好再选上“优质WINDOWS音频视频体验”,如果有无线网卡再选上“无线LAN服务”, ...

  10. Redis中的数据对象

    redis对象 redis中有五种常用对象 我们所说的对象的类型大多是值的类型,键的类型大多是字符串对象,值得类型大概有以下几种,但是无论哪种都是基于redisObject实现的 redisObjec ...