为了便于考虑,把删除反序变为增加
于是就变成关于权值和位置和时间的三维数点
一波cdq一波树状数组教做人
(神TM需要longlong,80了一发)
1 #include <bits/stdc++.h> 2 #define mid (l+r>>1) 3 #define ll long long 4 using namespace std; 5 ll n,ret,m,tem; 6 ll tr[200001],a[200001],in[200001]; 7 bool ok[200001]; 8 struct qu 9 { 10 ll num,pos,id,ans; 11 } q[200001],t[200001]; 12 bool com(qu a,qu b) 13 { 14 return a.id<b.id; 15 } 16 void add(ll x,ll y){ for(;x<=n;x+=x&-x) tr[x]+=y;} 17 ll que(ll x){ for(ret=0;x;x-=x&-x) ret+=tr[x];return ret;} 18 void cdq(ll l,ll r) 19 { 20 if(l==r) return; 21 cdq(l,mid);cdq(mid+1,r); 22 for(ll i=l,j=l,k=mid+1;i<=r;i++) 23 if((k>r) || (j<=mid && q[j].pos<q[k].pos)) t[i]=q[j++]; 24 else t[i]=q[k++]; 25 ll ALL=0; 26 for(ll i=l;i<=r;i++) 27 if((q[i]=t[i]).id>mid) 28 q[i].ans+=ALL-que(q[i].num); 29 else 30 add(q[i].num,1),++ALL; 31 for(ll i=l;i<=r;i++) 32 if(q[i].id<=mid) 33 add(q[i].num,-1); 34 for(ll i=r;i>=l;i--) 35 if(q[i].id>mid) 36 q[i].ans+=que(q[i].num); 37 else 38 add(q[i].num,1); 39 for(ll i=l;i<=r;i++) 40 if(q[i].id<=mid) 41 add(q[i].num,-1); 42 } 43 int main() 44 { 45 scanf("%d%d",&n,&m); 46 for(ll i=1;i<=n;i++) 47 scanf("%d",&tem),a[tem]=i; 48 for(ll i=1;i<=m;i++) 49 scanf("%d",&in[i]),ok[in[i]]=1; 50 tem=0; 51 for(ll i=1;i<=n;i++) 52 if(!ok[i]) 53 q[++tem].num=i,q[tem].pos=a[q[tem].num],q[tem].id=tem; 54 for(ll i=m;tem<=n;i--) 55 q[++tem].num=in[i],q[tem].pos=a[q[tem].num],q[tem].id=tem; 56 cdq(1,n); 57 sort(q+1,q+n+1,com); 58 for(ll i=2;i<=n;i++) 59 q[i].ans+=q[i-1].ans; 60 for(ll i=n;i>n-m;i--) 61 printf("%lld\n",q[i].ans); 62 return 0; 63 }