不得不说,线段树太神奇了,居然还可以这么玩。。。
题意:首先知道什么是最小逆序数对
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 5010;
const int INF = 1e8;
struct line
{
int l;
int r;
int value;
}tree[4 * N];
int a[N];
void build(int i, int l, int r)
{
tree[i].l = l;
tree[i].r = r;
tree[i].value = 0;
if(l == r) return;
int mid = (l + r) >> 1;
build(i*2, l, mid);
build(i*2+1, mid+1, r);
}
int query(int i, int l, int r)
{
if(tree[i].l == l && tree[i].r == r)
{
return tree[i].value;
}
int mid = (tree[i].l + tree[i].r) >> 1;
if(mid >= r) return query(i*2, l, r);
else if(mid < l) return query(i*2+1, l, r);
else return (query(i*2, l, mid) + query(i*2+1, mid+1, r));
}
void update(int i, int x)
{
if(tree[i].l <= x && tree[i].r >= x)
{
tree[i].value++;
}
if(tree[i].l == tree[i].r)
{
return;
}
int mid = (tree[i].l + tree[i].r) >> 1;
if(mid >= x) update(i*2, x);
else update(i*2+1, x);
}
int main()
{
// freopen("in.txt", "r", stdin);
int num, n, t;
while(~scanf("%d", &n))
{
build(1, 0, n-1);
int ans = 0;
for(int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
if(i != 0 && a[i] != n-1)
{
ans += query(1, a[i]+1, n-1);
}
update(1, a[i]);
}
int res = ans;
for(int i = 0; i < n; i ++)
{
ans += n-1-2*a[i];
if(ans < res) res = ans;
}
printf("%d\n", res);
}
return 0;
}