此题利用线段树/树状数组求逆序数。
关于逆序数有一个结论:数组循环移位逆序数sum=sum+n-2*in[i]-1,很容易想
#include<stdio.h>
#include<string.h>
int n;
int in[200010];
struct Tree{
int s;
int t;
int sum;
}tree[540000];
int min(int a,int b){
return a>b?b:a;
}
void build(int s,int t,int id){
tree[id].s=s;
tree[id].t=t;
tree[id].sum=0;
if(s!=t){
int mid=(s+t)>>1;
build(s,mid,id*2);
build(mid+1,t,id*2+1);
}
}
void update(int id,int i){
tree[id].sum+=1;
if(tree[id].s==tree[id].t && tree[id].s==i){
return;
}
int mid=(tree[id].s+tree[id].t)>>1;
if(mid>=i)
update(id*2,i);
else
update(id*2+1,i);
}
int query(int id,int s,int t){
if(tree[id].s==tree[id].t)
return tree[id].sum;
if(tree[id].s==s && t==tree[id].t)
return tree[id].sum;
int mid=(tree[id].s+tree[id].t)>>1;
if(mid>=t)
return query(id*2,s,t);
else if(s>mid)
return query(id*2+1,s,t);
else
return query(id*2,s,mid)+query(id*2+1,mid+1,t);
}
int main(){
int T,t,i,tem,mm;
while(scanf("%d",&n)!=EOF){
build(0,n-1,1);
int sum=0;
for(i=1;i<=n;i++){
scanf("%d",&in[i]);
sum+=query(1,in[i]+1,n-1);
update(1,in[i]);
}
int ans=sum;
for(i=1;i<=n;i++){
sum=sum+n-2*in[i]-1;
ans=min(ans,sum);
}
printf("%d\n", ans);
}
}