【题解】
分块,每块内部从小到大排序,每次询问,在完整的块内二分查找大于或小于 移动的值 的数的个数
复杂度:询问 O( m*sqrt(n) )
【代码】
#include<stdio.h> #include<stdlib.h> #define SIZE 128 int h[20005],a[20005],block[20005],L[200],R[200]; void jh(int* a,int* b) { int t=*a; *a=*b; *b=t; } void kp(int low,int high) { int i=low,j=high,mid=a[(i+j)/2]; while(i<j) { while(a[i]<mid) i++; while(a[j]>mid) j--; if(i<=j) { jh(&a[i],&a[j]); i++; j--; } } if(j>low) kp(low,j); if(i<high) kp(i,high); } int find_down(int num,int left,int right) { int mid; if(a[left]>=num) return left-1; while(left<right) { mid=(left+right+1)/2; if(a[mid]>=num) right=mid-1; else left=mid; } return left; } int find_up(int num,int left,int right) { int mid; if(a[right]<=num) return right+1; while(left<right) { mid=(left+right)/2; if(a[mid]<=num) left=mid+1; else right=mid; } return left; } int cx_down(int num,int x,int y) { int i,ans=0; if(block[x]+1>=block[y]) { for(i=x;i<=y;i++) if(h[i]<num) ans++; return ans; } for(i=x;i<=R[block[x]];i++) if(h[i]<num) ans++; for(i=L[block[y]];i<=y;i++) if(h[i]<num) ans++; for(i=block[x]+1;i<block[y];i++) ans+=find_down(num,L[i],R[i])-L[i]+1; return ans; } int cx_up(int num,int x,int y) { int i,ans=0; if(block[x]+1>=block[y]) { for(i=x;i<=y;i++) if(h[i]>num) ans++; return ans; } for(i=x;i<=R[block[x]];i++) if(h[i]>num) ans++; for(i=L[block[y]];i<=y;i++) if(h[i]>num) ans++; for(i=block[x]+1;i<block[y];i++) ans+=R[i]-find_up(num,L[i],R[i])+1; return ans; } int main() { int n,m,i,x,y,cnt,ans=0; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d",&h[i]); a[i]=h[i]; block[i]=(i-1)/SIZE+1; } cnt=(n-1)/SIZE+1; for(i=1;i<=cnt;i++) { L[i]=(i-1)*SIZE+1; R[i]=i*SIZE; } R[cnt]=n; for(i=1;i<=cnt;i++) kp(L[i],R[i]); for(i=1;i<=n;i++) ans+=cx_up(h[i],1,i-1); printf("%d\n",ans); scanf("%d",&m); for(;m>0;m--) { scanf("%d%d",&x,&y); if(x>y) jh(&x,&y); if(h[x]<h[y]) ans++; if(h[x]>h[y]) ans--; if(x+1<y) { ans=ans+cx_down(h[y],x+1,y-1)-cx_up(h[y],x+1,y-1); ans=ans-cx_down(h[x],x+1,y-1)+cx_up(h[x],x+1,y-1); } jh(&h[x],&h[y]); for(i=L[block[x]];i<=R[block[x]];i++) a[i]=h[i]; kp(L[block[x]],R[block[x]]); for(i=L[block[y]];i<=R[block[y]];i++) a[i]=h[i]; kp(L[block[y]],R[block[y]]); printf("%d\n",ans); } return 0; }