Minimum Inversion Number
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3973 Accepted Submission(s): 2380
For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:
a1, a2, ..., an-1, an (where m = 0 - the initial seqence)
a2, a3, ..., an, a1 (where m = 1)
a3, a4, ..., an, a1, a2 (where m = 2)
...
an, a1, a2, ..., an-1 (where m = n-1)
You are asked to write a program to find the minimum inversion number out of the above sequences.
//线段树基础题,求逆序数、应该没树状数组快
//这题可以改难点、就是这些数是不连续的、、、离散化、、
#include <iostream>
#include <stdio.h>
#include <string.h>
#define lson l,m,k<<1
#define rson m+1,r,k<<1|1
#define N 5003
using namespace std;
int st[N<<2];
void up(int &k)
{
st[k]=st[k<<1]+st[k<<1|1];
}
void build(int l,int r,int k)
{
if(l==r)
{
st[k]=0;
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
up(k);
}
void updata(int &index,int l,int r,int k)
{
if(l==r)
{
st[k]=1;
return ;
}
int m=(l+r)>>1;
if(index<=m) updata(index,lson);
else updata(index,rson);
up(k);
}
int query(int &L,int &R,int l,int r,int k)
{
if(L<=l&&R>=r)
{
return st[k];
}
int m=(l+r)>>1,te=0;
if(L<=m) te+=query(L,R,lson);
if(R>m) te+=query(L,R,rson);
return te;
}
int re[N];
int main()
{
int n,m;
int sum;
while(scanf("%d",&n)!=EOF)
{ n--;
build(0,n,1);
sum=m=0;
for(int i=0;i<=n;i++)
{
scanf("%d",&re[i]);
sum+=i-query(m,re[i],0,n,1);
updata(re[i],0,n,1);
}
m=sum;
for(int i=0;i<=n;i++)
{
sum=sum+n-re[i]-re[i];
if(sum<m)
m=sum;
}
printf("%d\n",m);
}
return 0;
}
// 下面是数组数组代码,果然更快,归并排序应该也很快的
#include <stdlib.h> #include <stdio.h> #include <string.h> #define N 5003 int tree[N]; int n; int lb(int x){return x&-x;} void up(int i) { for(;i<=n;tree[i]+=1,i+=lb(i)); } int gs(int i) { int sum=0; for(;i>0;sum+=tree[i],i-=lb(i)); return sum; } int main() { int a[N]; int i,sum,min; while(scanf("%d",&n)!=EOF) { memset(tree,0,sizeof(tree)); sum=0; for(i=1;i<=n;i++) {scanf("%d",&a[i]); up(a[i]+1); sum+=i-gs(a[i]+1);} min=sum; for(i=n;i>1;i--) { sum=sum+a[i]-(n-a[i]-1); min=min>sum?sum:min; } printf("%d\n",min); } return 0; }