*2300
线段树
不考虑\(b\)对自己的贡献,每次找最优方法插入\(b_i\),得到的\(b\)在\(c\)中一定递增。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2000010;
int T,a[N],b[N],n,m;
int res1[N],res2[N];
int ans[N<<2],tag[N<<2];
int ls(int x){return x<<1;}
int rs(int x){return x<<1|1;}
void push_up(int p){
ans[p]=min(ans[ls(p)],ans[rs(p)]);
}
void push_down(int p,int l,int r){
ans[ls(p)]+=tag[p];
ans[rs(p)]+=tag[p];
tag[ls(p)]+=tag[p];
tag[rs(p)]+=tag[p];
tag[p]=0;
}
void build(int l,int r,int p){
ans[p]=tag[p]=0;
ans[ls(p)]=tag[ls(p)]=ans[rs(p)]=tag[rs(p)]=0;
if(l==r){
return ;
}
int mid=(l+r)>>1;
build(l,mid,ls(p));
build(mid+1,r,rs(p));
}
void update(int l,int r,int nl,int nr,int p,int k){
if(nl<=l&&r<=nr){
ans[p]+=k;
tag[p]+=k;
return ;
}
push_down(p,l,r);
int mid=(l+r)>>1;
if(nl<=mid)update(l,mid,nl,nr,ls(p),k);
if(mid+1<=nr)update(mid+1,r,nl,nr,rs(p),k);
push_up(p);
}
int c[N];
long long int sum;
void qs(int l,int r){
if(l==r)return ;
int mid=(l+r)>>1;
qs(l,mid);qs(mid+1,r);
int kel=l;
for(int i=l,o=mid+1;i<=mid&&o<=r;){
if(a[i]<=a[o]){
c[kel++]=a[i++];
}
else{
c[kel++]=a[o++];
sum+=mid-i+1;
}
if(i==mid+1){
while(o<=r){
c[kel++]=a[o++];
}
}
if(o==r+1){
while(i<=mid){
c[kel++]=a[i++];
}
}
}
for(int i=l;i<=r;i++)a[i]=c[i];
}
int kk[N];
vector<int> v[N];
int main(){
scanf("%d",&T);
while(T--){
sum=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
kk[i]=a[i];
}
for(int i=1;i<=m;i++){
scanf("%d",&b[i]);
kk[i+n]=b[i];
}
sort(b+1,b+m+1);
sort(kk+1,kk+n+m+1);
int cnt=unique(kk+1,kk+n+m+1)-kk-1;
build(1,n+1,1);
for(int i=1;i<=n;i++){
a[i]=lower_bound(kk+1,kk+cnt+1,a[i])-kk;
v[a[i]].push_back(i);
update(1,1+n,i+1,n+1,1,1);
}
int pos1=1,pos2=1;
for(int i=1;i<=m;i++){
b[i]=lower_bound(kk+1,kk+cnt+1,b[i])-kk;
while(pos1<=b[i]){
int len=v[pos1].size();
for(int o=0;o<len;o++){
update(1,n+1,v[pos1][o]+1,n+1,1,-1);
}
pos1++;
}
while(pos2<b[i]){
int len=v[pos2].size();
for(int o=0;o<len;o++){
update(1,n+1,1,v[pos2][o],1,1);
}
pos2++;
}
sum+=ans[1];
}
qs(1,n);
printf("%lld\n",sum);
for(int i=1;i<=cnt;i++){
v[i].clear();
}
}
}
/*
*/