原題鏈接洛谷提高組-火柴排隊(duì)
分析
這題我是用離散化,數(shù)組映射(數(shù)據(jù)處理辦法),歸并排序優(yōu)化逆序?qū)?寫的。
關(guān)于(ai-bi)的平方 求和可以理解為 a組火柴和b組火柴 相對(duì)位置相等時(shí) 這個(gè)和最小
竟然有相對(duì)位置了就逃不了離散化數(shù)組了
對(duì)于求相鄰交換次數(shù),是不是很像冒泡排序。這時(shí)候就要引入逆序?qū)α恕?br>

可是這個(gè)逆序?qū)Φ膮⒄帐?,2,3,4,5的升序來判斷的,我們a轉(zhuǎn)成b的相對(duì)位置可不是
1,2,3,4,5來排的所以我們把b數(shù)組映射成1,2,3,4,5,然后把a(bǔ)數(shù)組也按照相同的映射方法改寫一下,再用逆序?qū)憽#ú挥锰谝庵貜?fù)的數(shù)據(jù),因?yàn)閮H大于才交換)
逆序?qū)τ贸R?guī)的暴力方法 時(shí)間雜復(fù)度過大,所以這里我用了歸并排序來優(yōu)化
總結(jié)
1,數(shù)據(jù)離散化
2,數(shù)組映射
3,逆序?qū)?/p>
代碼
點(diǎn)擊查看代碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100009;
struct data//結(jié)構(gòu)體離散化
{
ll val;
ll id;
}olda[N],oldb[N];
ll newa[N],copyy[N],a[N],b[N];
//為了好理解數(shù)組開的有點(diǎn)多,寫的時(shí)候可以省一些
bool cmp(struct data x,struct data y)
{
return x.val<y.val;
}
ll cnt=0,cup[N];
void merge(ll left,ll right)
{
if(left>=right)
{
return;
}
ll mid=(left+right)/2;
merge(left,mid);
merge(mid+1,right);
ll i=left,j=mid+1,k=left;
while(i<=mid && j<=right)
{
if(newa[i]<=newa[j])
{
cup[k++]=newa[i++];
}else
{
cup[k++]=newa[j++];
cnt+=mid-i+1;//與歸并排序相比就加了這兩條
cnt=cnt%99999997;
}
}
while(i<=mid)
{
cup[k++]=newa[i++];
}
while(j<=right)
{
cup[k++]=newa[j++];
}
for (int v=left;v<=right;v++)
{
newa[v]=cup[v];
}
}
int main()
{
int n;
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&olda[i].val);
olda[i].id=i;
}
for(int i=1;i<=n;i++)
{
scanf("%lld",&oldb[i].val);
oldb[i].id=i;
}
sort(olda+1,olda+1+n,cmp);
sort(oldb+1,oldb+1+n,cmp);
for(ll i=1;i<=n;i++)
{
a[olda[i].id]=i;
//不用特判相同時(shí)id相等,后面逆序?qū)Φ奶幚矸较蚩梢员苊庀嗟葧r(shí)相交換
//直接先出現(xiàn)的小
}
for(ll i=1;i<=n;i++)
{
b[oldb[i].id]=i;
}
//假設(shè)以b為參照物
//求逆序?qū)r(shí)暴力會(huì)超時(shí)所以可以進(jìn)行優(yōu)化,我用歸并優(yōu)化
//將第2盒火柴映射為升序,相當(dāng)于把第二盒當(dāng)成id為1,2,3,4,5然后把第一盒按id去改
for(ll i = 1; i <= n; i ++) copyy[b[i]] = i;//copyy作為按b轉(zhuǎn)化的表,想出這個(gè)方法的人真是天才!!
//將第1盒火柴當(dāng)對(duì)應(yīng)的元素進(jìn)行映射為第一種表示
for(ll i = 1; i <= n; i ++) newa[i] = copyy[a[i]];
merge(1,n);
printf("%lld\n",cnt%99999997);
return 0;
}

浙公網(wǎng)安備 33010602011771號(hào)