树状数组
一道很巧妙的题目所以我太菜根本想不到去看题解了。
首先按什么顺序移动最优:当然是大的先移喽。
可以考虑两棵平衡树模拟,但是高级数据结构实在太烦,于是我们想用简单的方法。
我们把第一个序列倒过来,然后和第二个拼起来。这道题就变成按照大小顺序计算与中间的两个“堆顶”之间的距离。我们把有记为1,无记为0。那么其实就是询问区间和并且单点修改。树状数组维护即可。
代码:
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define F inline
using namespace std;
typedef long long LL;
int n,m,i,p,q,a[N],b[N],t[N],c[N];
F char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF; return *l++;
}
F int _read(){
int x=0; char ch=readc();
while (!isdigit(ch)) ch=readc();
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
return x;
}
#define lbt(x) (x&(-x))
F void nsrt(int x,int p){ for (;x<=n;t[x]+=p,x+=lbt(x)); }
F int srch(int x){ for (i=0;x;i+=t[x],x-=lbt(x)); return i; }
int main(){
n=_read(),m=_read(),p=n,q=n+1,n+=m;
for (int i=p;i;i--) b[i]=a[i]=_read();
for (int i=p+1;i<=n;i++) b[i]=a[i]=_read();
sort(b+1,b+n+1); LL ans=0;
for (int i=1;i<=n;i++)
c[lower_bound(b+1,b+n+1,a[i])-b]=i;
for (int i=1;i<=n;i++) nsrt(i,1);
for (int i=n;i;i--){
if (c[i]>p) ans+=srch(c[i]-1)-srch(p),nsrt(c[i],-1),p=c[i];
else ans+=srch(p)-srch(c[i]),nsrt(c[i],-1),p=c[i];
}
return printf("%lld\n",ans),0;
}