Description
对于序列A,它的逆序对数定义为满足i
题解
cdq分治.
将删除操作倒序看就是加入操作,然后就是一个经典的三位偏序问题了。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100006
#define maxm 50006
#define lowbit(x) (x&-x)
#define LL long long
using namespace std;
inline char nc(){
static char buf[100000],*i=buf,*j=buf;
return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;
}
inline int _read(){
char ch=nc();int sum=0;
while(!(ch>='0'&&ch<='9'))ch=nc();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
return sum;
}
int n,m,nn,tem,t[maxn],a[maxn],b[maxn],p[maxn],f[maxn];
LL ans[maxm];
struct data{
int t,x,y;
bool operator <(const data&b)const{return x<b.x;}
}c[maxn],tmp[maxn];
bool vis[maxn];
void add(int x,int y){for(;x<=n;x+=lowbit(x))f[x]+=y;}
int get(int x){
int sum=0;
for(;x;x-=lowbit(x))sum+=f[x];
return sum;
}
void sort(int l,int r){
int mid=l+r>>1;
int i=l,j=mid+1;
for(int k=l;k<=r;k++)tmp[k]=c[k];
for(int k=l;k<=r;k++)
if(i<=mid&&(tmp[i]<tmp[j]||j>r))c[k]=tmp[i++];else c[k]=tmp[j++];
}
void work(int l,int r){
if(l>=r)return;
int mid=l+r>>1;
work(l,mid);work(mid+1,r);
int j=l;tem=0;
for(int i=mid+1;i<=r;i++){
while(j<=mid&&c[j].x<c[i].x)add(n-c[j].y+1,1),t[++tem]=n-c[j].y+1,j++;
ans[c[i].t]+=get(n-c[i].y+1);
}
for(int i=1;i<=tem;i++)add(t[i],-1);
j=mid;tem=0;
for(int i=r;i>mid;i--){
while(j>=l&&c[j].x>c[i].x)add(c[j].y,1),t[++tem]=c[j].y,j--;
ans[c[i].t]+=get(c[i].y);
}
for(int i=1;i<=tem;i++)add(t[i],-1);
sort(l,r);
}
int main(){
freopen("reverse.in","r",stdin);
freopen("reverse.out","w",stdout);
n=_read();m=_read();
memset(vis,1,sizeof(vis));
for(int i=1;i<=n;i++)a[i]=_read(),p[a[i]]=i;
for(int i=1;i<=m;i++)b[i]=_read(),vis[b[i]]=0;
for(int i=1;i<=n;i++)if(vis[a[i]])c[++nn].x=i,c[nn].y=a[i],c[nn].t=0;
for(int i=m;i>=1;i--)c[++nn].x=p[b[i]],c[nn].y=b[i],c[nn].t=m-i+1;
work(1,n);
for(int i=1;i<=m;i++)ans[i]+=ans[i-1];
for(int i=m;i>=1;i--)printf("%lld\n",ans[i]);
return 0;
}