您的位置:首页 > 其它

HDU1394 Minimum Inversion Number

2017-02-16 21:40 337 查看

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1394

题解:

题目大意:

给出n个数字(从0到n-1),题目给出的时候顺序已经打乱了,让你算出这些数字按题目移动构成最小的逆序数。(不会逆序数的谷歌一下)

这里我先讲下暴力的方法,先按逆序数的定义,先暴力的求出总和sum ,因为题目中一般都是把第一个数直接放在了最后,所以我们先假设要移动的数字为xi,那么比xi小的数字有xi,比xi大的数字有n-1-xi(因为数字的范围是0到n-1的),那么进行变化以后的sum应该为sum=sum-low(xi)+up(xi)。因为原本比xi要大的数字把xi放到后面以后就会构成了逆序列,从而增加了逆序数的数量。同理可得比xi要小的。因为数据的范围比较小,因此我们可以直接暴力来做。

暴力代码:

#include <cmath>
#include <cstdio>
#include <map>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
typedef long long ll;
const ll maxn = 5000+10;
int num[maxn];

int main()
{
int n;
while(cin>>n)
{
for(int i=0;i<n;i++)
cin>>num[i];
int sum=0;
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
if(num[i]>num[j])
sum++;
int temp=sum;
for(int i=0;i<n;i++)
{
temp=temp-num[i]+n-1-num[i];//sum=sum-low(num[i])+up(num[i])
sum=min(temp,sum);
}
cout<<sum<<endl;
}
}


本题还可以用线段树来进行优化,但是线段树优化的只是前面的暴力的代码,将原来n^2的代码优化到了n*log(n)的时间,优化的可以看作是是暴力代码中的第二个for。

线段树代码:

#include <cmath>
#include <cstdio>
#include <map>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
typedef long long ll;
const ll maxn = 5000+10;
#define lchild rt << 1, l, m
#define rchild rt << 1 | 1, m + 1, r
int tree[maxn<<2];
int x[maxn];

void push_up(int rt)
{
tree[rt]=tree[rt << 1]+tree[rt << 1 | 1];
}

void build(int rt,int l,int r)
{
tree[rt]=0;
if(l==r)
return;
int m=(l+r)>>1;
build(lchild);
build(rchild);
push_up(rt);
}

void updata(int pos,int rt,int l,int r)
{
if(l==r)
{
tree[rt]++;
return;
}
int m=(l+r)>>1;
if(pos<=m)
updata(pos,lchild);
else
updata(pos,rchild);
push_up(rt);
}

int query(int  L,int  R,int rt,int l,int  r)
{
if(L<=l&&R>=r)
return tree[rt];
int m=(l+r)>>1;
int ret=0;
if(L<=m)
ret+=query(L,R,lchild);
if(R>m)
ret+=query(L,R,rchild);
return ret;
}

int main()
{
int n;
while(cin>>n)
{
build(1,0,n-1);
int sum=0;
for(int i=0;i<n;i++)
{
cin>>x[i];
sum+=query(x[i],n-1,1,0,n-1);
updata(x[i],1,0,n-1);
}
int temp=sum;
for(int i=0;i<n;i++)
{
temp+=n-1-x[i]-x[i];
sum=min(temp,sum);
}
cout<<sum<<endl;
}
}

4000
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hdu 逆序数