HDU 3743 Frosh Week(树状数组或归并排序求逆序)
http://acm.hdu.edu.cn/showproblem.php?pid=3743
题意:
给你一个n排列,每次你只能交换相邻的两个整数,现在要你用最少的交换次数使得该排列呈递增排列。要你输出需要交换的次数。
分析:
首先这题类似于POJ2299:
http://blog.csdn.net/u013480600/article/details/21277047
其实题目就是给你n个数的排列,然后问你这n个数的逆序和是多少.可以用归并排序做,也可以用树状数组左,其中用树状数组做的话,每读入一个a[i],当前树状数组中先查找已经出现的比a[i]大的数有多少,即执行temp=sum(n)-sum(a[i]),然后这个temp就是a[i]的逆序,执行ans+=temp;然后在标记a[i]值已经出现过一次了,执行add(a[i],1)即可.
如果用归并排序做的话,参考刘汝佳的书.
AC代码:125ms归并排序
<span style="font-size:18px;">#include<cstdio>
using namespace std;
const int MAXN=500000+100;
int a[MAXN],b[MAXN];
long long merge_sort(int *a,int *b,int i,int j)//归并排序并返回逆序值,a为待排序的数组,b为辅助空间
{
if(i==j)return 0;
long long ans=0;//逆序值
int mid= (i+j)/2;
ans+=merge_sort(a,b,i,mid);//获取左边的逆序值
ans+=merge_sort(a,b,mid+1,j);//获取右边的逆序值
int p=i,q=mid+1,k=i;
while(p<=mid||q<=j)//获取左边与右边关联的逆序值
{
if(p>mid || (q<=j&&a[p]>a[q]))
{
b[k++]=a[q++];
ans+=mid-p+1;
}
else
{
b[k++]=a[p++];
}
}
for(int k=i;k<=j;k++)a[k]=b[k];
return ans;
}
int main()
{
long long ans;
int n;
while(scanf("%d",&n)==1&&n)
{
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
ans = merge_sort(a,b,0,n-1);
printf("%I64d\n",ans);
}
return 0;
}
</span>
AC代码:140ms,树状数组+离散化数据
<span style="font-size:18px;">#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1000000+10;
int c[MAXN];
int lowbit(int x)
{
return x&(-x);
}
int sum(int x)
{
int res=0;
while(x)
{
res +=c[x];
x-=lowbit(x);
}
return res;
}
void add(int x,int v)
{
while(x<MAXN)
{
c[x]+=v;
x+=lowbit(x);
}
}
struct node
{
int v;
int index;
bool operator <(const node &b)const
{
return v<b.v;
}
}nodes[MAXN];
int a[MAXN];
int main()
{
int n;
while(scanf("%d",&n)==1&&n)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&nodes[i].v);
nodes[i].index=i;
}
sort(nodes+1,nodes+n+1);
int max_num=1;
a[nodes[1].index]=1;
for(int i=2;i<=n;i++)
{
if(nodes[i].v==nodes[i-1].v)
a[nodes[i].index]=a[nodes[i-1].index];
else
a[nodes[i].index]=++max_num;
}
long long ans=0;
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)
{
int x=a[i];
add(x,1);
ans+= sum(n)-sum(x);
}
printf("%I64d\n",ans);
}
return 0;
}</span>