http://codevs.cn/problem/3286/
题面在 ↑ 面呢。
题意:让你求两个数列的最小差的平方和最少需要交换几次(只能周围交换)。刚开始听人说是求逆序对,我学了个归并就来搞这个题了。想了半天也没想明白怎么求逆序对啊。然后找了找题解。首先想什么时候保证两个数列差最小,一定是第一个数列第一大的对应第二个数列第一大的...依次类推。这样就可以再开两个数组记录一下他们的编号,然后利用sort结构体按照数的大小从小到大排序,最后开一个数组记录第一个数列中第一大的序号对应在第二个数列中第一大的序号是什么位置既 zh [ xh1 [ i ] ] = xh2 [ i ] 。然后求这个数组的逆序对,然后对答案去%输出。
归并排序求逆序对的思想:
二分出两个数组来,保证两个数组都是递增有序的,然后从两个数组中分别取出第一个数字比较,如果第二个数小于第一个数则ans+=第一个数组中剩下的数。正确性自行证明其实显然。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxx=100007;
struct ha
{
LL x,xh;
}y1[maxx];
ha y2[maxx];
LL zh[maxx],t[maxx];
LL n,ans=0;
void _marge(LL l,LL r)
{
if(l==r) return ;
LL mid=(l+r)/2;
_marge(l,mid);
_marge(mid+1,r);
LL pl=l,pr=mid+1,p=l;
while (pl<=mid || pr<=r)
{
if(pl>mid)
{
t[p]=zh[pr];
p++;
pr++;
}
else if(pr>r)
{
t[p]=zh[pl];
p++;
pl++;
}
else if(zh[pr]<zh[pl])
{
ans+=mid-pl+1;
t[p]=zh[pr];
p++;
pr++;
}
else
{
t[p]=zh[pl];
p++;
pl++;
}
}
for(int i=l;i<=r;i++)
zh[i]=t[i];
return ;
}
LL cp(ha a,ha b)
{return a.x<b.x;}
int main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&y1[i].x);
y1[i].xh=i;
}
for(int i=1;i<=n;i++)
{
scanf("%lld",&y2[i].x);
y2[i].xh=i;
}
sort(y1+1,y1+1+n,cp);
sort(y2+1,y2+1+n,cp);
for(int i=1;i<=n;i++)
zh[y1[i].xh]=y2[i].xh;
_marge(1,n);
printf("%lld",ans%99999997);
return 0;
}
树状数组求逆序对思想:(感谢lc的help)
给每个数组一个序号,然后sort结构体排序。然后按照序号放数。每次放之前用树状数组求一下当前序号的前缀和。ans+=每次前缀和。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxx=100007;
struct ha
{
LL x,xh;
}y1[maxx];
ha y2[maxx];
ha zh[maxx];
LL n,ans=0;
LL c[1000000];
void change(LL x,LL d)
{
while(x<=n)
{
c[x]+=d;
x+=x&(-x);
}
}
LL ask(LL x)
{
LL ans=0;
while(x>0)
{
ans+=c[x];
x-=x&(-x);
}
return ans;
}
LL cp(ha a,ha b)
{return a.x<b.x;}
LL cp2(ha a,ha b)
{return a.x>b.x;}
int main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&y1[i].x);
y1[i].xh=i;
}
for(int i=1;i<=n;i++)
{
scanf("%lld",&y2[i].x);
y2[i].xh=i;
}
sort(y1+1,y1+1+n,cp);
sort(y2+1,y2+1+n,cp);
for(int i=1;i<=n;i++)
zh[y1[i].xh].x=y2[i].xh;
for(int i=1;i<=n;i++)
zh[i].xh=i;
sort(zh+1,zh+1+n,cp2);
for(int i=1;i<=n;i++)
{
ans+=ask(zh[i].xh-1);
change(zh[i].xh,1);
}
printf("%lld",ans%99999997);
return 0;
}