考虑交换两个数的影响,发现只有夹在两个数中间的大于/小于两个数的数会产生影响,而两边的状态是不变的,然后就变成了序列分块的经典问题
注意细节.jpg
1 #include<cmath> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 const int N=20005,Sq=150; 8 int a[N],uni[N],blo[N],tra[N],pts[Sq][2]; 9 int n,m,t1,t2,sqr,cnt,len,ans; 10 vector<int> v[Sq]; 11 int prework() 12 { 13 sqr=sqrt(n)+10,pts[cnt=1][0]=1; 14 sort(uni+1,uni+1+n),len=unique(uni+1,uni+1+n)-uni-1; 15 for(int i=1;i<=n;i++) 16 { 17 a[i]=lower_bound(uni+1,uni+1+len,a[i])-uni; 18 blo[i]=(i-1)/sqr+1,v[blo[i]].push_back(a[i]); 19 if(i%sqr==0) pts[cnt++][1]=i,pts[cnt][0]=i+1; 20 } 21 pts[cnt][1]=n; 22 for(int i=1;i<=cnt;i++) 23 sort(v[i].begin(),v[i].end()); 24 int ret=0; 25 for(int i=1;i<=n;i++) 26 { 27 int tmp=len-a[i]+1,tep=tmp-1; 28 while(tep) ret+=tra[tep],tep-=tep&-tep; 29 while(tmp<=n) tra[tmp]++,tmp+=tmp&-tmp; 30 } 31 return ret; 32 } 33 int query(int x,int t) 34 { 35 int ret=0; 36 if(!t) 37 { 38 if(blo[t1]!=blo[t2]) 39 { 40 for(int i=t1;i<=pts[blo[t1]][1];i++) ret+=(a[i]<x); 41 for(int i=pts[blo[t2]][0];i<=t2;i++) ret+=(a[i]<x); 42 for(int i=blo[t1]+1;i<=blo[t2]-1;i++) 43 ret+=lower_bound(v[i].begin(),v[i].end(),x)-v[i].begin(); 44 } 45 else 46 for(int i=t1;i<=t2;i++) ret+=(a[i]<x); 47 } 48 else 49 { 50 if(blo[t1]!=blo[t2]) 51 { 52 for(int i=t1;i<=pts[blo[t1]][1];i++) ret+=(a[i]>x); 53 for(int i=pts[blo[t2]][0];i<=t2;i++) ret+=(a[i]>x); 54 for(int i=blo[t1]+1;i<=blo[t2]-1;i++) 55 ret+=v[i].size()-(upper_bound(v[i].begin(),v[i].end(),x)-v[i].begin()); 56 } 57 else 58 for(int i=t1;i<=t2;i++) ret+=(a[i]>x); 59 } 60 return ret; 61 } 62 void rebuild(int x,int y) 63 { 64 swap(a[x],a[y]); 65 int b1=blo[x],b2=blo[y]; if(b1==b2) return ; 66 v[b1].clear(),v[b2].clear(); 67 for(int i=pts[b1][0];i<=pts[b1][1];i++) 68 v[b1].push_back(a[i]); 69 for(int i=pts[b2][0];i<=pts[b2][1];i++) 70 v[b2].push_back(a[i]); 71 sort(v[b1].begin(),v[b1].end()); 72 sort(v[b2].begin(),v[b2].end()); 73 } 74 int main() 75 { 76 scanf("%d",&n); 77 for(int i=1;i<=n;i++) 78 scanf("%d",&a[i]),uni[i]=a[i]; 79 printf("%d ",ans=prework()); 80 scanf("%d",&m); 81 while(m--) 82 { 83 scanf("%d%d",&t1,&t2); 84 if(t1>t2) swap(t1,t2); 85 int a1=a[t1],a2=a[t2]; 86 if(t1!=t2-1) 87 { 88 t1++,t2--; 89 ans+=query(a1,1)-query(a1,0); 90 ans+=query(a2,0)-query(a2,1); 91 t1--,t2++; 92 } 93 if(a1<a2) ans++; if(a1>a2) ans--; 94 rebuild(t1,t2); printf("%d ",ans); 95 } 96 return 0; 97 }