题意:给出一列数组:a1,a2------an,一共有N个变形:
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)
求上面那种形式中逆序数对最少(树状数组)
难点:不能每次列举出N中类型,不然必导致TLE.
分析:每次将第一个数移到最后逆序对数将减少a[i]-1个,增加n-a[i]个。
所以公式为:minn=minn-(a[i]-1)+n-a[i];
附上代码:
#include <cstdio>
const int n=5110;
int c[n];//n为上限 数组的大小。
int a[n];
int lowbit(int x)
{
return x&(-x);
}
int sum(int n)
{
int t=0;
while(n>0)
{
t+=c[n];
n-=lowbit(n);
}
return t;
}
void add(int i,int x)
{
while(i<=n) //n为上限 数组的大小。
{
c[i]+=x;
i+=lowbit(i);
}
}
int main()
{
int k;
while(~scanf("%d",&k))
{
int ans=10000000;
int h=0;
for(int i=1;i<=k;i++)
{
int l;
scanf("%d",&l);
a[i]=++l;
}
int minn=0;
for(int j=0;j<=k;j++)
c[j]=0;
for(int j=1;j<=k;j++)
{
add(a[j],1);
minn=minn+(sum(k)-sum(a[j]));
}
int s=minn;
for(int i=1;i<k;i++)
{
s=s-(a[i]-1)+k-a[i];//s记录上一个没有移动时的逆序数对
if(s<minn)
minn=s;
}
printf("%d\n",minn);
}
return 0;
}