두 개의 말뚝을 모으고 분할 지점을 중간으로 설정합니다. 삭제는 숫자의 내림차순으로 만 수행 할 수 있기 때문에 실제로 쓸모없는 작업을 반복하지 않는 한 작업 횟수는 확실합니다.
먼저 숫자를 정렬하고 숫자의 위치를 기록합니다. 가장 큰 것에서 가장 작은 것까지 삭제합니다. 각 숫자의 위치와 구분 점 사이의 거리에 따라 각 숫자를 삭제할 이동 횟수를 계산합니다. 숫자를 삭제 한 후 그에 따라 구분 점의 위치를 이동합니다.
현재 가장 큰 숫자를 삭제하고 싶지만 한 힙의 숫자가 힙의 맨 위에 있지 않은 경우 동일한 힙의 작은 숫자를 모두 다른 힙으로 이동해야하며 이동 한 후에는 두 힙을 이동해야합니다. 숫자는 변경되며 mid는 두 파일 사이의 분할 지점 위치를 나타냅니다.
특정 번호가 삭제되면 단일 수정 지점이 수행됩니다. 데이터 구조를 사용하여 간격 합계 값을 유지하고 간격 합계 값을 쿼리합니다.
#include <bits/stdc++.h>
#define int long long
#define lowbit(x) x&(-x)
using namespace std;
const int N=1e5+5;
int n1,n2,n,now,ans;
int c[N];
struct number{
int x,pos;}num[N];
inline void change(int x,int v)
{
while (x<=n)
{
c[x]+=v;
x+=lowbit(x);
}
}
inline int query(int x)
{
int res=0;
while (x)
{
res+=c[x];
x-=lowbit(x);
}
return res;
}
inline bool cmp(number a,number b){
return a.x>b.x;}
signed main(){
scanf("%lld%lld",&n1,&n2);
n=n1+n2+1;
now=n1+1;
for (register int i=n1; i>=1; --i) scanf("%lld",&num[i].x),num[i].pos=i,change(i,1);
for (register int i=n1+2; i<=n; ++i) scanf("%lld",&num[i].x),num[i].pos=i,change(i,1);
num[now].pos=now;
sort(num+1,num+n+1,cmp);
for (register int i=1; i<n; ++i)
{
change(num[i].pos,-1);
if (now<num[i].pos) ans+=query(num[i].pos)-query(now);
else ans+=query(now)-query(num[i].pos);
now=num[i].pos;
}
printf("%lld\n",ans);
return 0;
}