逆序对__归并排序__树状数组 Inversions SGU - 180

There are N integers (1<=N<=65537) A1, A2,.. AN (0<=Ai<=10^9). You need to find amount of such pairs (i, j) that 1<=i<j<=N and A[i]>A[j].
Input
The first line of the input contains the number N. The second line contains N numbers A1...AN.
Output
Write amount of such pairs.

Sample test(s)
Input
5
2 3 1 5 4

Output
3
题目的数据范围有点大,但是可以直接归并排序过了。 如果要用树状数组则需要先离散化。
 
归并做法:
 
#include <cstdio>
#include <iostream>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cstring>
#include <string>
#include <sstream>
#include <cmath>
#include <cstdlib>
#include <algorithm>

#define sf scanf
#define pf printf
#define fp(x) freopen((x), "r", stdin)

typedef long long ll;

using namespace std;

const int maxn = 1e5;

int qarr[maxn];
ll qans; //long long   不然会over 

void merge(int arr[], int left, int right, int tarr[])
{
    if (left>=right) return ;
    int m = (left + right) >> 1;
    merge(arr, left, m, tarr);
    merge(arr, m+1, right, tarr);
    int i, j, cnt;
    i = left;
    j = m + 1;
    cnt = 0;
    while (i<=m && j<=right) {
        if (arr[i] <= arr[j]) 
            tarr[cnt++] = arr[i++];
        else {
            tarr[cnt++] = arr[j++];
            qans += (m - i +  1);
        }
            
    }
    while (i<=m) tarr[cnt++] = arr[i++];
    while (j<=right) tarr[cnt++] = arr[j++];
    for (i=0; i<cnt; ++i) arr[left++] = tarr[i]; 
}

void mergesort(int arr[], int left, int right)
{
    int *p = new int[right-left+1];
    merge(arr, left, right, p);
} 

int main()
{
    int n;
    sf("%d", &n);
     
    for (int i=1; i<=n; ++i) sf("%d", &qarr[i]);
    
    mergesort(qarr, 1, n);
    cout << qans << endl;
    
    return 0;
} 
View Code

 

树状数组做法:
 
#include <cstdio>
#include <iostream>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cstring>
#include <string>
#include <sstream>
#include <cmath>
#include <cstdlib>
#include <algorithm>

#define sf scanf
#define pf printf
#define fp(x) freopen((x), "r", stdin)

typedef long long ll;

using namespace std;

const int maxn = 1e5;

struct nobe{
    int id;
    int val;
    int ls;
    bool operator < (const nobe &a) const {
        if (val != a.val) return val < a.val;
        return id < a.id;
    }
}te[maxn];

int qsum[maxn];
ll qans;

bool cmp(const nobe &a, const nobe &b)
{
    return a.id < b.id;
}

inline int lowbit(int id)
{
    return id&-id;
}

int update(int id, int _maxn)
{
    while (id <= _maxn) {
        qsum[id] += 1;
        id+=lowbit(id);
    }
} 

int getsum(int id)
{
    int res = 0;
    while (id) {
        res += qsum[id];
        id -= lowbit(id);
    }
    return res;
}

int main()
{
    int n;
    sf("%d", &n);
     
    for (int i=1; i<=n; ++i) {
        sf("%d", &te[i].val);
        te[i].id = i;
    }
    sort(te+1, te+1+n);
    int lst = te[1].val;
    int cnt = 1;
    for (int i=1; i<=n; ++i) te[i].val = i;
    sort(te+1, te+1+n, cmp); 
    for (int i=1; i<=n; ++i) {
        update(te[i].val, n);
        qans += i - 1 - getsum(te[i].val-1);
    }
    cout << qans << endl;
    
    return 0;
} 
View Code

 

 
posted @ 2018-04-02 20:34  过路人1998  阅读(141)  评论(0编辑  收藏  举报