先建立一个空的树;
在读入数据的过程中不断更新树,并计算出最初的序列的逆序对有多少;
还应知道每次将新的序列的第一个y[i]移到最后,sum将减少y[i]个,当然同时还会增加n-1-y[i];
例如:第一个是3 那么这个序列在3这个位置上必有0,1,2 即减少y[i]个;这三个逆序对;但以前不是3的逆序对
这时却是3的逆序对,即加上n-1-y[i]; 最后求出最小的值即可;
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 5005;
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define MID(a, b) ((a+b)>>1)
int y[maxn], n;
struct node
{
int lft, rht, value;
int mid()
{
return MID(lft, rht);
}
};
struct Segtree
{
node tree[maxn*4];
void build(int lft, int rht, int inf)
{
tree[inf].lft = lft;
tree[inf].rht = rht;
tree[inf].value = 0;
if(lft != rht)
{
int mid = tree[inf].mid();
build(lft, mid, LL(inf));
build(mid+1, rht, RR(inf));
}
}
void update(int pos, int inf)
{
int lft = tree[inf].lft, rht = tree[inf].rht;
if(lft == rht) tree[inf].value++;
else
{
int mid = tree[inf].mid();
if(pos<=mid) update(pos, LL(inf));
else update(pos, RR(inf));
tree[inf].value = tree[LL(inf)].value + tree[RR(inf)].value;
}
}
int query(int st, int en, int inf)
{
int lft = tree[inf].lft, rht = tree[inf].rht;
if(st<=lft && rht<=en) return tree[inf].value;
else
{
int mid = tree[inf].mid();
int sum1 = 0, sum2 = 0;
if(st <= mid) sum1 = query(st, en, LL(inf));
if(mid < en) sum2 = query(st, en, RR(inf));
return sum1+sum2;
}
}
}seg;
int main()
{
while(scanf("%d", &n) != EOF)
{
seg.build(0, n-1, 1);
int sum = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d", &y[i]);
seg.update(y[i], 1);
if(y[i] != n-1) sum += seg.query(y[i]+1, n-1, 1);
}
int mi = sum;
for(int i = 1; i <= n; i++)
{
sum -= y[i];
sum += n-1-y[i];
mi = min(mi, sum);
}
printf("%d\n", mi);
}
return 0;
}