您的位置:首页 > 其它

HDU 1394 Minimum Inversion Number

2015-08-08 22:31 417 查看
题目大意:

求Inversion后的最小逆序数。

解题思路:

用O(nlogn)复杂度求出最初逆序数后,就可以用O(1)的复杂度分别递推出其他解。

线段树维护,比当前叶子节点小的叶子节点个数。

写了一份暴力,一份线段树,线段树的效率大概是暴力的八倍以上。

暴力

#include<cstdio>
int a[5555];
int main()
{
    int n,i,j,ans=999999999;
    while(scanf("%d",&n)!=EOF)
    {
        ans=999999999;
           for(i=0;i<n;i++) scanf("%d",&a[i]);
           int cnt=0;
           for(i=0;i<n;i++)
               for(j=i+1;j<n;j++)
               {
                   if(a[i]>a[j]) cnt++;
               }
           // printf("cnt=%d\n",cnt);
           if(ans>cnt)  ans=cnt;
           for(i=0;i<n;i++)
           {
               cnt=cnt-a[i]+n-1-a[i];
               if(ans>cnt)  ans=cnt;
            }
           printf("%d\n",ans);
    }
    return 0;
}


线段树

#include<cstdio>
#include<cstring>
#include<cmath>
#define maxn 5555
using namespace std;
int sum[maxn<<2];
int max(int x,int y){
if (x>y) return x;
else return y;
}
int min(int x,int y){
if (x<y) return x;
else return y;
}
void PushUP(int rt){
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt){
sum[rt]=0;
if (l==r) return ;
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
}
void update(int p,int l,int r,int rt){
if (l==r) {
sum[rt]++;
return ;
}
int mid=(l+r)>>1;
if (p<=mid) update(p,l,mid,rt<<1);
else update(p,mid+1,r,rt<<1|1);
PushUP(rt);
}
int query(int L,int R,int l,int r,int rt){
if (L<=l && r<=R) {
return sum[rt];
}
int mid=(l+r)>>1;
int ret=0;
if (L<=mid) ret+=query(L,R,l,mid,rt<<1);
if (R>=mid) ret+=query(L,R,mid+1,r,rt<<1|1);
return ret;
}
int x[maxn];
int main(){
int n;
while (~scanf("%d",&n)){
build(0,n-1,1);
int sum=0;
for (int i=0;i<n;i++){
scanf("%d",&x[i]);
sum+=query(x[i],n-1,0,n-1,1);
update(x[i],0,n-1,1);
}
int ret=sum;
for (int i=0;i<n;i++){
sum+=n-x[i]-x[i]-1;
ret=min(ret,sum);
}
printf("%d\n",ret);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: