poj 2299 Ultra-QuickSort(线段树/树状数组/归并 求逆序对)

Problem: 2299		User: shu_dayang
Memory: 7380K		Time: 500MS
Language: C++		Result: Accepted
Source Code//树状数组
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
typedef long long LL;
#define MAXN  500005
#define MID(l,r) ((l + r) >> 1)
using namespace std;

int c[MAXN],aa[MAXN];
int n;

struct Node
{
    int val;
    int order;
}a[MAXN];

bool cmp(Node a, Node b)
{
    return a.val < b.val;
}

int lowbit(int x)
{
    return x &(-x);
}

void update(int x)
{
    while(x <= n)
    {
        c[x] += 1;
        x += lowbit(x);
    }
}

int query(int x)
{
    int sum = 0;
    while(x > 0)
    {
        sum += c[x];
        x -= lowbit(x);
    }
    return sum;
}

int main()
{
    LL ans;
    while(~scanf("%d",&n) && n != 0)
    {
        memset(c,0,sizeof(c));
        for(int i = 1; i <= n; i++)
        {
            scanf("%d",&a[i].val);
            a[i].order = i;
        }
        sort(a+1,a+1+n,cmp);
        for(int i = 1; i <= n; i++)
            aa[a[i].order] = i;

        ans = 0;
        for(int i = 1; i <= n; i++)
        {
            update(aa[i]);
            ans += i - query(aa[i]);
        }
        printf("%I64d\n",ans);
    }
    return 0;
}
时间: 2024-11-03 01:25:23

poj 2299 Ultra-QuickSort(线段树/树状数组/归并 求逆序对)的相关文章

Inversion (hdu 4911 树状数组 || 归并排序 求逆序对)

Inversion Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 2003    Accepted Submission(s): 787 Problem Description bobo has a sequence a1,a2,-,an. He is allowed to swap two adjacent numbers fo

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

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

HDU 1394 树状数组+离散化求逆序数

对于求逆序数问题,学会去利用树状数组进行转换求解方式,是很必要的. 一般来说我们求解逆序数,是在给定一串序列里,用循环的方式找到每一个数之前有多少个比它大的数,算法的时间复杂度为o(n2). 那么我们通过树状数组可以明显提高时间效率. 我们可以按照排列的顺序依次将数字放入树状数组中,并依次更新预与之相关联的树状数组元素.那么在将其更新完毕后,我们知道每个数对应的树状数组元素的左边的数肯定比它小,我们在以序列顺序依次更新树状数组时,如果有值在它前面出现,那么它对应的树状数组元素(在这个题目里存放的

【BZOJ3295】【块状链表+树状数组】动态逆序对

Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数.以下n行每行包含一个1到n之间的正整数,即初始排列.以下m行每行一个正整数,依次为每次删除的元素. Output 输出包含m行,依次为删除每个元素之前,逆序对的个数. Sample Input 5 4 1 5 3

树状数组之求逆对数

Ultra-QuickSort 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 s

POJ2299 Ultra-QuickSort【树状数组】【逆序数】

题目链接: http://poj.org/problem?id=2299 题目大意: 给你一个包含N个整数的序列,只能通过交换相邻的数字,最终变为升序顺序,问:最少需要多少次交换. 思路: 其实就是问冒泡排序的交换次数.其实就是求原序列的逆序数.用归并排序.线段树.树状数组都可以做. 但是如果用线段树和树状数组来做的话,因为元素个数是500000,但是元素值范围却是999999999,需 要先离散化.这里用间接排序的方法.用一个数组Arr[]存放原序列的值,另一个数组Id[]存放原序列编号 (1

【bzoj2789】[Poi2012]Letters 树状数组求逆序对

题目描述 给出两个长度相同且由大写英文字母组成的字符串A.B,保证A和B中每种字母出现的次数相同. 现在每次可以交换A中相邻两个字符,求最少需要交换多少次可以使得A变成B. 输入 第一行一个正整数n (2<=n<=1,000,000),表示字符串的长度. 第二行和第三行各一个长度为n的字符串,并且只包含大写英文字母. 输出 一个非负整数,表示最少的交换次数. 样例输入 3 ABC BCA 样例输出 2 题解 树状数组求逆序对 一个结论:将序列A通过交换相邻元素变换为序列B,需要的最小次数为A中

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

前几天开始看树状数组了,然后开始找题来刷. 首先是 POJ 2299 Ultra-QuickSort: http://poj.org/problem?id=2299 这题是指给你一个无序序列,只能交换相邻的两数使它有序,要你求出交换的次数.实质上就是求逆序对,网上有很多人说它的原理是冒泡排序,可以用归并排序来求出,但我一时间想不出它是如何和归并排序搭上边的(当初排序没学好啊~),只好用刚学过的树状数组来解决了.在POJ 1990中学到了如何在实际中应用上树状数组,没错,就是用个特殊的数组来记录即

poj 2299 Ultra-QuickSort(归并排序或是bit 树+离散化皆可)

题意:给一个数组,计算需要的冒泡排序的次数,元素个数很大,不能用n^2的冒泡排序计算. 解析:这题实际上就是求逆序对的个数,可以用归并排序的方法,我这里用另一种方法写,bit树+离散化.由于元素的值可以达到很大,但元素个数最多只有500000个,可以先对这些数排序,离散化一下,比如5个数:1 5 8  233333333 122222,排序后他们对应的标号可以是1 2 3 5 4:每次插入一个数时add(val,1),计算该数以及之前所有的数的个数sum(val);那么逆序对的个数=当前这个数的