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

题目就是让你求逆序数,用树状数组很简单,不过数据太大,要先进行离散化,将数据范围压缩到1~n以内。还有poj竟然不支持c++11,害得我lambda表达式编译错误。


#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <map>
#include <vector>
#include <list>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <limits>
#include <new>
#include <utility>
#include <iterator>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <ctime>
using namespace std;

const int maxn = 500010;
int bit[maxn], n;

struct ST
{
    int num, index;
};

ST a[maxn];

//树状数组求和
int sum(int i)
{
    int s = 0;
    while (i > 0)
    {
        s += bit[i];
        i &= i - 1;
    }
    return s;
}

//树状数组修改元素
void add(int i, int x)
{
    while (i <= n)
    {
        bit[i] += x;
        i += i & (-i);
    }
}

int main()
{
    while (scanf("%d", &n) == 1 && n)
    {
        memset(bit, 0, sizeof(bit));
        for (int i = 0; i < n; ++i)
        {
            scanf("%d", &a[i].num);
            a[i].index = i;
        }

        //离散化
        sort(a, a+n, [](ST a, ST b){ return a.num < b.num; });
        int cnt = 0, tmp;
        for (int i = 0; i < n; ++i)
            if (!i || a[i].num != tmp)
            {
                tmp = a[i].num;
                a[i].num = ++cnt;
            }
            else
            {
                tmp = a[i].num;
                a[i].num = cnt;
            }
        sort(a, a+n, [](ST a, ST b){ return a.index < b.index; });

        //树状数组求逆序数
        long long ans = 0;
        for (int i = 0; i < n; ++i)
        {
            ans += i - sum(a[i].num);
            add(a[i].num, 1);
        }
        cout << ans << endl;
    }
    return 0;
}


原文地址:https://www.cnblogs.com/godweiyang/p/12203962.html