题解 UVA299 【Train Swapping】
whatismyname0 · · 个人记录
逆序对模板题,逆序对一般正解是
但
归并排序运用的是“分而治之”的思想,首先把数组
然后我们把这个操作反过来做一遍,把这些部分按照分裂的顺序合并起来。
在合并的过程中,我们要保证每一个部分当前都是有序的,所以我们需要在合并的过程中更改原来的数组,而更改的过程中又需要读取当前合并的两个部分的元素,所以不妨再声明一个临时数组
有了临时数组,我们就可以快乐的合并了,首先我们声明两个指针
当
以上就是合并与统计的操作,我们不断执行这个操作,不断递归就可以用
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
int n,c[500001],tmp[500001];
long long ans;
void go(int l,int r)
{
if (l>=r)return;
int mid=(l+r)>>1;
go(l,mid);
go(mid+1,r);
int i=l,j=mid+1,zz=l;
while (i<=mid&&j<=r)
{
if (c[j]<c[i])
{
tmp[zz]=c[j];
zz++;
ans+=mid+1-i;
j++;
}
if (c[j]>=c[i])
{
tmp[zz]=c[i];
zz++;
i++;
}
}
while (i<=mid)
{
tmp[zz]=c[i];
zz++;
i++;
}
while (j<=r)
{
tmp[zz]=c[j];
zz++;
j++;
}
for (i=l;i<=r;i++)c[i]=tmp[i];
}
int main()
{
int T;
cin>>T;
while (T--)
{
ans=0;
cin>>n;
for (int i=1;i<=n;i++)cin>>c[i];
go(1,n);
cout<<"Optimal train swapping takes "<<ans<<" swaps.\n";
}
}