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