如果 i<j a[i]>a[j] 就是倒置数 ,然后从原始序列,把首元素依次后移,形成的新序列,求出每个队列的倒置数的对数,要注意的一点就是如果首元素为3,最大元素为10,将3移到最后,倒置数则增加了7个(45678910),减少了2个(12),所以由第一个序列的倒置数可以推出循环右移后的序列的倒置数对数,详细看代码注释
题目链接 点击打开链接
代码注释:
<strong><span style="font-size:18px;color:#ff6600;">#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
#define N 5000+10
struct node
{
int l,r,sum;
} a[N*3];
int s[N];
void build(int l,int r,int i)
{
a[i].l=l;
a[i].r=r;
a[i].sum=0;
if(l==r)
return ;
int mid=(l+r)/2;
build(l,mid,2*i);
build(mid+1,r,2*i+1);
}
void update(int l,int i)
{
a[i].sum++; //每个元素进来标记一下
if(a[i].l==a[i].r)
return ;
int mid=(a[i].l+a[i].r)/2;
if(l<=mid)
update(l,2*i);
else
update(l,2*i+1);
}
int query(int l,int r,int i)
{
if(a[i].l==l&&a[i].r==r)
return a[i].sum;
int mid=(a[i].l+a[i].r)/2;
if(r<=mid)
return query(l,r,2*i);
else if(l>mid)
return query(l,r,2*i+1);
else
return query(l,mid,2*i)+query(mid+1,r,2*i+1);
}
int main()
{
int n,i;
while(cin>>n)
{
build(1,n,1);
int sum=0;
for(i=1; i<=n; i++)
{
scanf("%d",&s[i]);
sum+=query(s[i]+1,n,1);//这里记数原理就是加上每个元素后面的数出现的次数,出现的次数在update里开头可以记数
update(s[i]+1,1);
}
int ans=sum;
for(i=1; i<=n; i++)
{
sum+=n-s[i]-1-s[i];
ans=min(sum,ans);
}
cout<<ans<<endl;
}
}</span></strong>
本文介绍了一种计算数组中倒置数的方法,并通过构建区间树进行更新和查询操作来优化计算过程。对于长度为n的序列,文章提供了一个算法,能够通过循环右移的方式快速计算出每个状态下的倒置数数量。
655

被折叠的 条评论
为什么被折叠?



