题解:
将前n个数看作插入,后m个数仍看作删除。
然后就是cdq分治。
代码:
#include#include #include using namespace std;#define N 150050#define ll long longinline int rd(){ int f=1,c=0;char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();} return f*c;}int n,m;struct node{ int a,b,c,d;}p[N],tmp[N];int pos[N];ll ans[N];int f[N];void up(int x,int d){ if(!x)return ; while(x<=100000)f[x]+=d,x+=(x&(-x));}int down(int x){ if(!x)return 0; int ret = 0; while(x)ret+=f[x],x-=(x&(-x)); return ret;}void Sort(int l,int r){ int mid = (l+r)>>1; int i=l,j=mid+1,k=l; while(i<=mid&&j<=r) { while(p[i].a<=p[j].a&&i<=mid) { tmp[k]=p[i]; i++,k++; } while(p[i].a>p[j].a&&j<=r) { tmp[k]=p[j]; j++,k++; } } while(i<=mid) { tmp[k]=p[i]; i++,k++; } while(j<=r) { tmp[k]=p[j]; j++,k++; } for(i=l;i<=r;i++) p[i]=tmp[i];}void cdq(int l,int r){ if(l==r)return ; int mid = (l+r)>>1; cdq(l,mid),cdq(mid+1,r); Sort(l,mid),Sort(mid+1,r); int i,j; j = l; for(i=mid+1;i<=r;i++) { while(j<=mid&&p[i].a>=p[j].a)up(p[j].b,p[j].d),j++; ans[p[i].c]+=p[i].d*(down(n)-down(p[i].b)); } for(j=j-1;j>=l;j--)up(p[j].b,-p[j].d); j = mid; for(i=r;i>mid;i--) { while(j>=l&&p[i].a<=p[j].a)up(p[j].b,p[j].d),j--; ans[p[i].c]+=p[i].d*down(p[i].b-1); } for(j=j+1;j<=mid;j++)up(p[j].b,-p[j].d);}int main(){ n=rd(),m=rd(); for(int x,i=1;i<=n;i++) { x=rd(); p[i].a=i,p[i].b=x,p[i].c=0,p[i].d=1; pos[x]=i; } for(int x,j,i=1;i<=m;i++) { x=rd();j=i+n; p[j].a=pos[x],p[j].b=x,p[j].c=i,p[j].d=-1; } cdq(1,n+m); for(int i=1;i<=m;i++)ans[i]+=ans[i-1]; for(int i=0;i