【題解】
將兩堆物品拼接到一起,物品的移動次數等價於中間的"斷點"的移動距離之和
通過排序預處理出每次刪除後的下一個該刪除的位置
每個物品代表一條長度爲1的線段,該物品刪除後,線段長度改爲0
然後兩點之間的距離就轉化爲了區間和,用樹狀數組維護即可
【代碼】
#include<stdio.h>
#include<stdlib.h>
typedef long long LL;
int a[100005],b[100005],c[100005];
int n;
void jh(int* a,int* b)
{
int t=*a;
*a=*b;
*b=t;
}
void xg(int p,int i)
{
for(;i<=n;i+=i&(-i))
c[i]+=p;
}
LL cx(int i)
{
int ans=0;
for(;i>0;i-=i&(-i))
ans+=c[i];
return (LL)ans;
}
void kp(int low,int high)
{
int i=low,j=high,mid=a[(i+j)/2];
while(i<j)
{
while(a[i]>mid) i++;
while(a[j]<mid) j--;
if(i<=j)
{
jh(&a[i],&a[j]);
jh(&b[i],&b[j]);
i++;
j--;
}
}
if(j>low) kp(low,j);
if(i<high) kp(i,high);
}
int main()
{
LL ans=0;
int n1,n2,i,p;//p:當前斷點在第幾個元素之前
scanf("%d%d",&n1,&n2);
for(i=n1;i>=1;i--)
scanf("%d",&a[i]);
for(i=n1+1;i<=n1+n2;i++)
scanf("%d",&a[i]);
p=n1+1;
n=n1+n2;
for(i=1;i<=n;i++)
{
b[i]=i;
xg(1,i);
}
kp(1,n);
for(i=1;i<=n;i++)
{
if(p>b[i])
{
ans+=cx(p-1)-cx(b[i]);
p=b[i]+1;
}
else
{
ans+=cx(b[i]-1)-cx(p-1);
p=b[i];
}
xg(-1,b[i]);
}
printf("%lld",ans);
return 0;
}