传送门:Ultra-Quicksort
题意:求一个序列的逆序数。
分析:数据范围太大,需要先离散化处理。所谓离散化,就是缩小数与数之间的间隔,但要保证原来的大小关系不变。
然后是求逆序数,用归并排序的算法或者树状数组皆可。
-----1. 树状数组求逆序数
# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
using namespace std;
//AC 407ms
const int maxn = 500000 + 5;
int a[maxn], c[maxn];
int n;
struct num{
int val, pos;
bool operator<(const num &a) const{
return val < a.val;
}
}b[maxn];
int lowbit(int x)
{
return x & -x;
}
void add(int x)
{
for(int i = x; i <= maxn; i += lowbit(i))
c[i]++;
}
int sum(int x)
{
int s = 0;
for(int i = x; i ; i -= lowbit(i))
s += c[i];
return s;
}
void solve()
{
long long ans = 0;
for(int i = 1; i <= n; ++i)
{
add(a[i]);
ans += i - sum(a[i]);
}
cout << ans << endl;
}
void process() //离散化处理
{
for(int i = 1; i <= n; ++i)
{
scanf("%d", &b[i].val);
b[i].pos = i;
}
stable_sort(b + 1, b + n + 1);
for(int i = 1; i <= n; ++i)
a[b[i].pos] = i;
}
int main()
{
while(cin >> n && n)
{
process();
memset(c, 0, sizeof(c));
solve();
}
return 0;
}
-----2. 归并求逆序数
# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
using namespace std;
//AC, 516ms
const int maxn = 500000 + 5;
int a[maxn], tmp[maxn];
int n;
long long ans;
struct num{
int val, pos;
bool operator<(const num &a) const{
return val < a.val;
}
}b[maxn];
void Merge(int a[], int tmp[], int left, int mid, int right)
{
int i = left, j = mid + 1;
int k = left;
while(i <= mid && j <= right)
{
if(a[i] < a[j]){
tmp[k++] = a[i++];
}
else{
ans += mid - i + 1;
tmp[k++] = a[j++];
}
}
while(i <= mid) tmp[k++] = a[i++];
while(j <= right) tmp[k++] = a[j++];
for(i = left; i <= right; ++i)
a[i] = tmp[i];
}
void MSort(int a[], int tmp[], int left, int right)
{
if(left < right)
{
int mid = (left + right) >> 1;
MSort(a, tmp, left, mid);
MSort(a, tmp, mid + 1, right);
Merge(a, tmp, left, mid, right);
}
}
void solve()
{
MSort(a, tmp, 1, n);
cout << ans << endl;
}
void process()
{
for(int i = 1; i <= n; ++i)
{
scanf("%d", &b[i].val);
b[i].pos = i;
}
stable_sort(b + 1, b + n + 1);
for(int i = 1; i <= n; ++i)
a[b[i].pos] = i;
}
int main()
{
while(cin >> n && n)
{
ans = 0;
process();
solve();
}
return 0;
}