POJ 2299 Ultra-QuickSort (树状数组 && 离散化&&逆序)

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

分析:其实经过一次模拟后,会发现奇妙的东西,这个排序都是按位置排的,最大要求到最大,最小要去到最小,转化思想这是一道求逆序对数的题目,答案就是逆序对数。

这里数据过大999999999,数组无法开的了这么大,我们可以离散化,只记录相对大小。

这里离散化有所不同,这里为了压时,用了空间换时间的方法. 前面的文章有讲到sum(i)表示前面有多少比这个小的数,可以sum(n)-sum(i), 这里有新知识就是sum(i)表示有多少小的数,那当前的总数是i,那大的数就是(i-sum(i)这也是求逆序对的方法,目测挺快的。

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
int a[100];
int b[100],c[100],n;
int lowbit(int x)
{
    return x&(-x);
}
void add(int k,int num) {
    while(k<=n) {
        c[k]+=num;
        k+=lowbit(k);

    }
}
int sum(int k) {
    int ans=0;
    while(k) {
        ans+=c[k];
        k-=lowbit(k);

    }
    return ans;
}
int main( )
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(c,0,sizeof(c));
        if(n==0)
        break;
        for(int i=0 ; i<n ; i++)
        {
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        sort(b,b+n);
        int summ=0;

        for(int i=0 ; i<n ; i++)
        {
          a[i] = (lower_bound(b,b+n,a[i])-b)+1;
          summ+=(sum(n)-sum(a[i]));
          //summ+=(i-sum(a[i]+1)
          add(a[i],1);
        }
        printf("%d\n",summ);

    }
}

原文地址:https://www.cnblogs.com/shuaihui520/p/9119706.html

时间: 2024-10-11 23:31:10

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

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

题目链接:http://poj.org/problem?id=2299 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

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

http://poj.org/problem?id=2299 题意:给出一组数,求逆序对. 思路: 这道题可以用树状数组解决,但是在此之前,需要对数据进行一下预处理. 这道题目的数据可以大到999,999,999,但数组肯定是无法开这么大的,但是每组数据最多只有500000个,那么,怎么办呢,离散化! 离散化,也就是将数据和1~n做一一映射. 比如: 9 1 0 5 4 离散化之后变成 5 2 1 4 3 这样的话,就可以放心的开数组啦! 至于树状数组的计算过程,我懒得写了,直接摘抄一下大神的h

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

Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 46080   Accepted: 16763 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swappin

poj2299(离散化+树状数组求逆序)

数据范围比较大,先用离散化将数据映射到可控的范围,然后应用树状数组求逆序求解. 总共有N个数,如何判断第i+1个数到最后一个数之间有多少个数小于第i个数呢?不妨假设有一个区间 [1,N],只需要判断区间[i+1,N]之间有多少个数小于第i个数.如果我们把总区间初始化为0,然后把第i个数之前出现过的数都在相应的区间把它的值定为1,那么问题就转换成了[i+1,N]值的总和.再仔细想一下,区间[1,i]的值+区间[i+1,N]的值=区间[1,N]的值(i已经标记为1),所以区间[i+1,N]值的总和等

poj 2299 Ultra-QuickSort (树状数组+离散化)

Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 48257   Accepted: 17610 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swappin

POJ 2299 Ultra-QuickSort (树状数组)

前段时间用归并排序写了这题,发现树状数组也能解这题,就去学习了一下 首先先来看一个序列   6 1 2 7 3 4 8 5,此序列的逆序数为5+3+1=9.冒泡法可以直接枚举出逆序数,但是时间复杂度太高O(n^2).冒泡排序的原理是枚举每一个数组,然后找出这个数后面有多少个数是小于这个数的,小于它逆序数+1.仔细想一下,如果我们不用枚举这个数后面的所有数,而是直接得到小于这个数的个数,那么效率将会大大提高. 总共有N个数,如何判断第i+1个数到最后一个数之间有多少个数小于第i个数呢?不妨假设有一

POJ 2299 Ultra-QuickSort(树状数组)

Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 47014   Accepted: 17182 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swappin

树状数组+离散化+DFS序+离线 HDOJ 4358 Boring counting

题目传送门 题意:给你一棵树,树上的每个节点都有树值,给m个查询,问以每个点u为根的子树下有多少种权值恰好出现k次. 分析:首先要对权值离散化,然后要将树形转换为线形,配上图: 收获: //还没写完... 代码: /************************************************ * Author :Running_Time * Created Time :2015/9/10 星期四 19:15:22 * File Name :I.cpp ************

POJ 3067 Japan(树状数组/求逆序数)

Japan Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22258   Accepted: 5995 Description Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island with N cities on the East coas