1. 程式人生 > >51nod 1019 逆序數

51nod 1019 逆序數

序列 lowbit define class algo ash def sam out

在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麽它們就稱為一個逆序。一個排列中逆序的總數就稱為這個排列的逆序數。

如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序數是4。給出一個整數序列,求該序列的逆序數。

Input第1行:N,N為序列的長度(n <= 50000)
第2 - N + 1行:序列中的元素(0 <= Aii <= 10^9)Output輸出逆序數Sample Input

4
2
4
3
1

Sample Output

4

逆序數如上所述,就是一對數的前後位置與大小順序相反,即前面的數大於後面的數,這個東西裏離散還會講的,

這道題需要先離散數據,要不TLE的

樹狀數組的代碼如下

#include <stdio.h>
#include <algorithm>
using namespace std;
const int N = 500005;
struct Node
{
    int val;
    int pos;
    friend bool operator <(Node a,Node b)
    {
        return a.val < b.val;
    }
};
Node node[N];
int c[N], hash[N], n;
int lowbit(int
x) { return x & (-x); } void update(int x) { while (x <= n) { c[x] += 1; x += lowbit(x); } } int getsum(int x) { int sum = 0; while (x > 0) { sum += c[x]; x -= lowbit(x); } return sum; }
int main() { scanf("%d", &n);
for (int i = 1; i <= n; ++i) { scanf("%d", &node[i].val); node[i].pos = i; } sort(node + 1, node + n + 1); for (int i = 1; i <= n; ++i) hash[node[i].pos] = i; int ans = 0; for (int i = 1; i <= n; ++i) { update(hash[i]); ans += i - getsum(hash[i]); } printf("%d\n", ans); return 0; }

TLE的代碼

#include <bits/stdc++.h>
using namespace std;
#define N 500005
int c[N];
int n;
int lowbit(int i)
{
    return i&(-i);
}
int insert(int i,int x)
{
    while(i<=n)
    {
        c[i]+=x;
        i+=lowbit(i);
    }
    return 0;
}

int getsum(int i)
{
    int sum=0;
    while(i>0)
    {
        sum+=c[i];
        i-=lowbit(i);
    }
    return sum;
}int main()
{
    while(cin>>n)
    {
        int ans=0;
        memset(c,0,sizeof(c));
        for(int i=1; i<=n; i++)
        {
            int a;
            cin>>a;
            insert(a,1);
            ans+=i-getsum(a);
        }
        cout<<ans<<endl;
    }
    return 0;
}

51nod 1019 逆序數