Title
Solution
对于逆序对,要满足
i
<
j
,
a
[
i
]
.
t
i
m
e
<
a
[
j
]
.
t
i
m
e
,
a
[
i
]
.
z
>
a
[
j
]
.
z
i<j,a[i].time<a[j].time,a[i].z>a[j].z
i<j,a[i].time<a[j].time,a[i].z>a[j].z
i
<
j
i<j
i<j可以在cdq中维持
然后根据
a
[
i
]
.
z
>
a
[
j
]
.
z
a[i].z>a[j].z
a[i].z>a[j].z累计
a
[
i
]
.
t
i
m
e
<
a
[
j
]
.
t
i
m
e
a[i].time<a[j].time
a[i].time<a[j].time,用树状数组统计。
正序做, a [ i ] . a n s a[i].ans a[i].ans表示 i i i的满足条件的逆序对,累减即可。
code
#include<cstdio>
#include<algorithm>
#include<string>
#define rep(i,x,y) for(register int i=x;i<=y;++i)
#define ll long long
using namespace std;
const int N=1e5+10;
int n,m,b[N],sz; ll ans;
struct treearray{
int q[N*2];
void add(int x,int y){for(;x<=n+1;x+=(x&(-x))) q[x]+=y;}
int ask(int x){int ans=0; for(;x>0;x-=(x&(-x))) ans+=q[x]; return ans;}
}T;
struct node{
int z,del,ans;
}a[N];
inline int read(){
int p=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) p=(p<<3)+(p<<1)+c-48,c=getchar();
return p;
}
inline bool cmp1(node x,node y){
return x.z<y.z;
}
inline bool cmp2(node x,node y){
return x.del<y.del;
}
void cdq(int l,int r){
if (r-l==1) return;
int mid=(l+r)/2,i,j;
cdq(l,mid); cdq(mid,r);
i=l+1,j=mid+1;
while (i<=mid){
while (a[i].z>a[j].z&&j<=r) T.add(a[j].del,1),j++;
a[i].ans+=T.ask(m+1)-T.ask(a[i].del),i++;
}
i=l+1,j=mid+1;
while (i<=mid){
while (a[i].z>a[j].z&&j<=r) T.add(a[j].del,-1),j++;
i++;
}
i=mid,j=r;
while (j>mid){
while (a[i].z>a[j].z&&i>l) T.add(a[i].del,1),i--;
a[j].ans+=T.ask(m+1)-T.ask(a[j].del),j--;
}
i=mid,j=r;
while (j>mid){
while (a[i].z>a[j].z&&i>l) T.add(a[i].del,-1),i--;
j--;
}
sort(a+l+1,a+r+1,cmp1);
return;
}
int main(){
n=read(),m=read();
rep(i,1,n) a[i].z=read(),b[a[i].z]=i;
rep(i,1,m) a[b[sz=read()]].del=i;
rep(i,1,n) if (a[i].del==0) a[i].del=m+1;
rep(i,1,n) ans+=T.ask(n+1)-T.ask(a[i].z),T.add(a[i].z,1);
rep(i,1,n) T.add(a[i].z,-1);
cdq(0,n);
sort(a+1,a+n+1,cmp2);
rep(i,1,m) printf("%lld\n",ans),ans-=a[i].ans;
return 0;
}