1. 程式人生 > >HDU-6318 Swaps and Inversions(雜湊+逆序數)

HDU-6318 Swaps and Inversions(雜湊+逆序數)

求逆序數的方法:

 a[i]   3 2 1 5 4

ind:1 2 3 4 5

1)樹狀陣列

當i=1,查詢1 - a[i]有幾個存在,即在i之前輸入 ,且值小於a[i] ,那麼這些數是非逆序數個數。累加最後n*(1+n)/2 - cnt 求得

2)線段樹

當i= 1時,查詢a[i]-n 有幾個存在,即在i之前輸入的 ,切值大於a[i],那麼這些數就是逆序數。 也可按1)方式做

雜湊:

由於輸入包含負數,而陣列的下標不允許有負數,那麼必須重新給 a[i] 一個編號, 且新編號的大小關係不能變,最小的還是最小的。

for(int i=1;i<=n;i++)
{
    scanf("%d",&node[i].date);
    node[i].ind = i;
}

sort(node+1,node+n+1,cmp); // 按date從小到大排序

 hash[node[1].ind] = 1;
int cnt = 2;
for(int i=2;i<=n;i++)
{
    if(node[i].date == node[i-1].date)
        hash[node[i].ind] = cnt;
    else hash[node[i].ind] = cnt++;
}

//這樣a[i]被賦予了新的非負值

code:

#include<stdio.h>
#include <cstdio>
#include<fstream>
#include<string>
#include <bitset>
#include<iostream>
#include<stdlib.h>
#include<map>
#include<vector>
#include<stack>
#include <algorithm>
#include <cstring>
//#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mmax = 1e5 + 5;
const int mod = 9901;
int dp;
int ans[mmax],ans1[mmax];
struct da
{
    int date;
    int num;
    bool operator <(const da&b)const
    {
        return date<b.date;
    }
} a[mmax];
int lowbit(int x)
{
    return x&(-x);
}
int sum(int x)
{
    int sum = 0;
    while (x>0)
    {
        sum += ans[x];
        x -= lowbit(x);
    }
    return sum;
}

void add(int x,int d)
{
    while (x<=mmax)
    {
        ans[x]+=d;
        x += lowbit(x);
    }
}

int main()
{
    ll  n, x,y, left, right;
    ll mans;
    while (scanf("%lld%lld%lld", &n,&x,&y)!=EOF)
    {
        mans = 0;
        memset(ans, 0, sizeof(ans));
        memset(ans1, 0, sizeof(ans1));
        for (int i = 1; i <= n; i++)
        {
            scanf("%d",&a[i].date);

            a[i].num = i;

        }
        sort(a + 1, a + n + 1);
        int index = 1;
        ans1[a[1].num] = 1;
        for (int i = 2; i <= n; i++)
        {
            if (a[i].date == a[i - 1].date)
                ans1[a[i].num] = index;
            else
                ans1[a[i].num] = ++index;
        }
        for (int i = 1; i <= n; i++)
        {
            mans+=sum(ans1[i]);
            add(ans1[i],1);
        }
        mans=n*(n-1)/2-mans;
        cout<<(mans*min(x,y))<<endl;
    }
    //system("pause");
    return 0;
}