Block is a good algorithm
Especially for me this will not fool the tree cover tree
When deleting a number, it is difficult to find the contribution to the reverse number of the number which is bigger than its front number + behind it it is smaller than the number , then use the block is very easy:
1. The contribution calculation block front and rear half of the number of blocks, the block in its violence;
2. delete it, marking the original number of columns, the number of blocks after deletion of the back move forward.
Write complexity is $ O (m \ sqrt {n} logn) $, very dangerous, but we have found that the block size is taken as $ \ sqrt {nlogn} $, then the complexity dropped to $ O (m \ sqrt {nlogn}) $, often without cards can easily AC.
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N=100050; char rB[1<<21],*S,*T,wB[1<<21]; int wp=-1; inline char gc(){return S==T&&(T=(S=rB)+fread(rB,1,1<<21,stdin),S==T)?EOF:*S++;} inline void flush(){fwrite(wB,1,wp+1,stdout);wp=-1;} inline void pc(char c){if(wp+1==(1<<21))flush();wB[++wp]=c;} inline int rd(){ char c=gc(); while(c<48||c>57)c=gc(); int x=c&15; for(c=gc();c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c&15); return x; } short buf[25]; inline void wt(ll x){ short l=-1; while(x>9){ buf[++l]=x%10; x/=10; } pc(x|48); while(l>=0)pc(buf[l--]|48); pc('\n'); } //快读/快写 int a[N],b[100][1300],c[N],t[N],n,x,sz[100],K,cnt,pos[N]; ll ans=0; bool d[N]; void ms(int L,int R){ //归并排序求初始逆序对数 if(L==R)return; int M=L+R>>1,i=L,j=M+1,k=L; ms(L,M);ms(M+1,R); while(i<=M&&j<=R)if(c[i]<=c[j])t[k++]=c[i++]; else{ ans+=M-i+1; t[k++]=c[j++]; } while(i<=M)t[k++]=c[i++]; while(j<=R)t[k++]=c[j++]; for(i=L;i<=R;i++)c[i]=t[i]; } inline void build(){ int i,j; K=sqrt(n*log(n)/log(2));if(!K)K=1;cnt=n/K; //1*log(1)=0,碰上毒瘤数据(这题没有)会RE for(i=1;i<=cnt;i++){ for(j=1;j<=K;j++)b[i][j]=a[(i-1)*K+j]; Sort (B [I] + . 1 , B [I] + K + . 1 ); SZ [I] = K; } IF (n-% K) { CNT ++ ; for (I = . 1 ; I <= n-% K; I ++) B [CNT] [I] = A [(the CNT- . 1 ) * K + I]; Sort (B [CNT] + . 1 , B [CNT] + n-% K + . 1 ); SZ [CNT] = n-% K ; } } inline void inupper ( int P, int X) { // half a larger value in the block number int L = . 1, R & lt SZ = [P], m, S = SZ [P] + . 1 ; the while (L <= R & lt) { m = L + R & lt >> . 1 ; IF (B [P] [m]> X) {S = m; R & lt = M- . 1 ;} the else L = m + . 1 ; } ANS - = SZ [P] -s + . 1 ; } inline void inlower ( int P, int X) { // the block half a smaller value of a number int L = . 1 , R & lt SZ = [P], m, S = 0 ; the while (L <= R & lt) { m = L + R & lt >> . 1 ; IF(b[p][m]<x){s=m;l=m+1;} else r=m-1; } ans-=s; } inline int find(int p,int x){ //暴力搜 int l=1,r=sz[p],m; while(l<r){ m=l+r>>1; if(b[p][m]>=x)r=m; else l=m+1; } return l; } inline void work(){ int p=(x+K-1)/K,i,t=find(p,a[x]); for(i=1;i<p;i++)inupper(i,a[x]); for(i=p+1;i<=cnt;i++)inlower(i,a[x]); for(i=(p-1)*K+1;i<x;i++)if(!d[i]&&a[i]>a[x])ans--; for(i=x+1;i<=p*K&&i<=n;i++)if(!d[i]&&a[i]<a[x])ans--; d[x]=1; //删除标记 for(i=t;i<sz[p];i++)b[p][i]=b[p][i+1]; //Deletion of a count to advance behind SZ [P] -; // within this block reduction element } int main () { int m, I; n- = RD (); RD = m () - . 1 ; // Now that a final output not answer, then not processed for (I = . 1 ; I <= n-; I ++) POS [a [I] = RD ()] = I; // Title to be deleted is the number, so to note the location Build (); the memcpy ( C, A, the sizeof (C)); MS ( . 1 , n-); wt (ANS); the while (M-- ) { X = POS [RD ()]; Work (); wt (ANS); } the flush ( ); return 0 ; }
Then I will not have to learn tree cover tree