/*******************************************
Date:2014/9/30
Author:fisty
hdu1394 线段树
每次把x从0移到最后时
因为序列为[0, n-1],若最前面一个数为x,序列中比x
小的数为[0, x-1], 共x个,比x大的数为[x+1, n-1],
共n-x-1个,将x移到最后,比x小的数的逆序数均减1,
x的前面比x大的数有n-x-1个,x的逆序数增加n-x-1。
所以新序列的逆序数为原序列的逆序数加上n-2*x-1。
***********************************************/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lson l, m, k << 1
#define rson m+1, r, k << 1 | 1
#define MAX_N 5005
struct tree{
int dat[MAX_N << 2];
void build(int l, int r, int k){
if(l == r){
dat[k] = 0;
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
dat[k] = dat[k << 1] + dat[k << 1 | 1];
}
void update(int p,int l,int r, int k){
if(l == r){
dat[k]++;
return ;
}
int m = (l + r) >> 1;
if(p <= m) update(p,lson);
else update(p,rson);
dat[k] = dat[k << 1] + dat[k << 1 | 1];
}
int query(int a, int b, int l, int r, int k){
if(l >= a && r <= b){
return dat[k];
}
int m = (l + r) >> 1;
int sum = 0;
if(a <= m) sum += query(a, b, lson);
if(b > m) sum += query(a ,b, rson);
return sum;
}
}seg;
int y[MAX_N];
int main(){
int t;
while(scanf("%d", &t) != EOF){
seg.build(0, t-1, 1);
int sum = 0;
for(int i = 0;i < t; i++){
scanf("%d", &y[i]);
sum += seg.query(y[i],t - 1, 0, t-1, 1);
seg.update(y[i], 0, t-1, 1);
}
int ans = sum;
for(int i = 0;i < t ;i++){
sum = sum + t - 2 * y[i] - 1;
if(sum < ans) ans = sum;
}
printf("%d\n", ans);
}
return 0;
}
hdu1394 逆序数-线段树
最新推荐文章于 2019-03-03 18:34:38 发布