HDU-6318 Swaps and Inversions(哈希+逆序数)

http://acm.hdu.edu.cn/showproblem.php?pid=6318

求逆序数的方法:

 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;
}

猜你喜欢

转载自blog.csdn.net/qq_37591656/article/details/81220458
今日推荐