傳送門node
題解ios
聽別人說這是洛谷用戶的雙倍經驗啊……然而根本沒有感受到……由於另外的那題我是用樹狀數組套主席樹作的……並且莫名其妙感受那種方法思路更清晰(雖然碼量稍稍大了那麼一點點)……感謝Candy大佬教會了我CDQ的動態逆序對……莫名其妙1A了……git
由於是刪除,因此能夠當作倒着加入。並且沒規定都在$n$之內,因此要離散。咱們把每個位置都表示成一個三元組$(t,x,y)$,其中$t$表示加入的時間,$x$表示在原數組中的位置,$y$表示離散以後的值。求逆序對,就表明求有多少個三元組知足$t'<t,x'<x,y'>y$或$t'<t,x'>x,y'<y$。咱們能夠先把時間這一維排序,而後CDQ的時候順便排好$x$這一維,$y$這一維用樹狀數組求解。由於要找兩種,因此CDQ的時候要兩個分別找,這一部分的細節能夠參考代碼數組
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 #define ll long long 6 using namespace std; 7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 8 char buf[1<<21],*p1=buf,*p2=buf; 9 inline int read(){ 10 #define num ch-'0' 11 char ch;bool flag=0;int res; 12 while(!isdigit(ch=getc())) 13 (ch=='-')&&(flag=true); 14 for(res=num;isdigit(ch=getc());res=res*10+num); 15 (flag)&&(res=-res); 16 #undef num 17 return res; 18 } 19 char sr[1<<21],z[20];int C=-1,Z; 20 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} 21 inline void print(ll x){ 22 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; 23 while(z[++Z]=x%10+48,x/=10); 24 while(sr[++C]=z[Z],--Z);sr[++C]=' '; 25 } 26 const int N=4e4+5; 27 int n,m,c[N],ty,yy[N]; 28 inline void add(int x,int val){ 29 for(;x<=ty;x+=x&-x) c[x]+=val; 30 } 31 inline int query(int x){ 32 int res=0; 33 for(;x;x-=x&-x) res+=c[x]; 34 return res; 35 } 36 inline void clear(int x){ 37 for(;x<=ty;x+=x&-x) 38 if(c[x]) c[x]=0;else break; 39 } 40 struct node{ 41 int t,x,y; 42 node(){} 43 node(int t,int x,int y):t(t),x(x),y(y){} 44 bool operator <(const node &b)const 45 {return x==b.x?y<b.y:x<b.x;} 46 }a[N],p[N]; 47 inline bool cmptime(const node &a,const node &b){ 48 return a.t==b.t?a.x<b.x:a.t<b.t; 49 } 50 ll ans[N]; 51 void CDQ(int l,int r){ 52 if(l==r) return; 53 int mid=l+r>>1; 54 CDQ(l,mid),CDQ(mid+1,r); 55 for(int i=l,j=l,k=mid+1;i<=r;){ 56 if(k>r||(j<=mid&&a[j]<a[k])) add(a[j].y,1),p[i++]=a[j++]; 57 else ans[a[k].t]+=query(n)-query(a[k].y),p[i++]=a[k++]; 58 } 59 for(int i=l;i<=mid;++i) clear(a[i].y); 60 for(int i=l;i<=r;++i) a[i]=p[i]; 61 for(int i=r;i>=l;--i){ 62 if(a[i].t<=mid) add(a[i].y,1); 63 else ans[a[i].t]+=query(a[i].y-1); 64 } 65 for(int i=l;i<=r;++i) clear(a[i].y); 66 } 67 int main(){ 68 //freopen("testdata.in","r",stdin); 69 n=read(),m=read(); 70 for(int i=1;i<=n;++i){ 71 yy[i]=read(),a[i]=node(0,i,yy[i]); 72 } 73 sort(yy+1,yy+1+n); 74 ty=unique(yy+1,yy+1+n)-yy-1; 75 for(int i=1;i<=n;++i) a[i].y=lower_bound(yy+1,yy+1+ty,a[i].y)-yy; 76 int Time=n; 77 for(int i=1;i<=m;++i){ 78 int k=read();a[k].t=Time--; 79 } 80 for(int i=1;i<=n;++i) if(!a[i].t) a[i].t=Time--; 81 sort(a+1,a+1+n,cmptime); 82 CDQ(1,n); 83 for(int i=1;i<=n;++i) ans[i]+=ans[i-1]; 84 for(int i=n;i>=n-m;--i) print(ans[i]); 85 Ot(); 86 return 0; 87 }