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