考虑是把序列中的元素插入到序列中,序列插入的相对位置一定是值小的在前面。
对,当前得到对逆序数,之间值在之间的元素有个,值大于的元素有个,值小于的元素有个,那么交换和插入的相对位置后当前的逆序数个数为个。故得证。
枚举,对序列,小于的位置设为0,大于的位置设为1,(等于的情况稍后考虑),那么插在之前构成的逆序数的对数等于中1的个数加上中0的个数(的时候等于中0的个数,的时候等于中1的个数)。
考虑,所有的位置都是,那么插在之前构成的逆序数的对数等于。
插入时,部分位置由变为,位置的变为0,导致逆序对数+1,逆序对数-1。
对于等于的位置,和不构成逆序数,但对构成逆序数。
先离散化
code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e6+7,mod=998244353 ;
int t[maxn<<2],n,m,lazy[maxn<<2];
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline void build(int l,int r,int rt) {
lazy[rt]=0;
if(l==r) {
t[rt]=l-1;
return;
}
int mid=(l+r)/2;
build(lson);
build(rson);
t[rt]=min(t[rt<<1],t[rt<<1|1]);
}//0插在pos之前
void pushdown(int rt) {
if(lazy[rt]) {
t[rt<<1]+=lazy[rt];
t[rt<<1|1]+=lazy[rt];
lazy[rt<<1]+=lazy[rt];
lazy[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
}
inline void update(int x,int y,int val,int l,int r,int rt) {
if(x>y) return;
if(x<=l&&r<=y) {
t[rt]+=val;
lazy[rt]+=val;
return;
}
pushdown(rt);
int mid=(l+r)/2;
if(y<=mid) update(x,y,val,lson);
else if(x>mid) update(x,y,val,rson);
else {
update(x,y,val,lson);
update(x,y,val,rson);
}
t[rt]=min(t[rt<<1],t[rt<<1|1]);
}
int tr[maxn];
inline void add(int x) {
while(x<=n+m+1) {
tr[x]+=1;
x+=(x&-x);
}
}
inline int qry(int x) {
int res(0);
while(x) {
res+=tr[x];
x-=(x&-x);
}
return res;
}
inline void solve() {
int cnt(0),pos(1);
ll res(0);
cin>>n>>m;
vector<int>a(n+1),b(m+1),A(n+m+1);
vector<pair<int,int> >p(n+1);
map<int,int>mp;
for(int i=1;i<=n+m+1;++i) tr[i]=0;
for(int i=1;i<=n;++i) {
cin>>a[i],A[i]=a[i];
}
for(int i=1;i<=m;++i) cin>>b[i],A[i+n]=b[i];
sort(A.begin()+1,A.end());
sort(b.begin()+1,b.end());
int nm=unique(A.begin()+1,A.end())-A.begin();
for(int i=1;i<=n;++i) a[i]=lower_bound(A.begin()+1,A.begin()+nm,a[i])-A.begin();
for(int i=1;i<=m;++i) b[i]=lower_bound(A.begin()+1,A.begin()+nm,b[i])-A.begin();
for(int i=n;i;--i) {
res+=qry(a[i]-1),add(a[i]);
p[i].first=a[i],p[i].second=i;
}
sort(p.begin()+1,p.end());
build(1,n+1,1);
ll ans(0);
for(int i=1;i<=m;++i) {
while(pos<=n&&p[pos].first<b[i]) {
update(1,p[pos].second,1,1,n+1,1);
update(p[pos].second+1,n+1,-1,1,n+1,1);
++pos;
}
if(b[i]!=b[i-1]) for(int j=pos;j<=n&&p[j].first==b[i];++j)
update(p[j].second+1,n+1,-1,1,n+1,1);
ans+=t[1];
if(b[i]!=b[i+1]||i==m) while(pos<=n&&p[pos].first==b[i]) {
update(1,p[pos].second,1,1,n+1,1);
++pos;
}
}
cout<<ans+res<<'\n';
}
int main() {
cin.sync_with_stdio(false), cin.tie(nullptr),cout.tie(nullptr);
int _=1;
cin>>_;
while(_--) solve();
return 0;
}