BZOJ 2141 排队(分块+树状数组)
题意
第一行为一个正整数n,表示小朋友的数量;第二行包含n个由空格分隔的正整数h1,h2,…,hn,依次表示初始队列中小朋友的身高;第三行为一个正整数m,表示交换操作的次数;以下m行每行包含两个正整数ai和bi,表示交换位置ai与位置bi的小朋友。
输出文件共m行,第i行一个正整数表示交换操作i结束后,序列的杂乱程度(逆序对数)。
1≤m≤2*10^3,1≤n≤2*104,1≤hi≤109,ai≠bi,1≤ai,bi≤n。
题解
难受,PE看成RE,下了数据手测20组发现没有问题,最后发现多了一个endl;
然后有重复但并不用去重。
分块做法
首先离散化,分块,对于每块建立一个树状数组,保存这个块中的所有元素
然后对于每个询问(x,y) (x<y) 两侧的数是没有影响的,区间(x,y)的数a[i]讨论如下:
a[i]<a[x] --ans
a[i]>a[x] ++ans
a[i]<a[y] ++ans
a[i]>a[y] --ans
然后对于块中的树状数组处理,块外的暴力
然后附上分块VSCDQ(上面的是分块)
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 const int N=21000; 8 int n,a[N],b[N],block[N],Block,size[N],L[N],R[N],m,tr[500][N],ans; 9 int lowbit(int x){ 10 return x&-x; 11 } 12 void add(int id,int x,int w){ 13 for(int i=x;i<=n;i+=lowbit(i)){ 14 tr[id][i]+=w; 15 } 16 } 17 int getsum(int id,int x){ 18 int tmp=0; 19 for(int i=x;i;i-=lowbit(i)){ 20 tmp+=tr[id][i]; 21 } 22 return tmp; 23 } 24 int main(){ 25 // freopen("20.in","r",stdin); 26 // freopen("xdx.out","w",stdout); 27 scanf("%d",&n); 28 Block=sqrt(n); 29 for(int i=1;i<=n;i++){ 30 scanf("%d",&a[i]); 31 b[i]=a[i]; 32 block[i]=(i-1)/Block+1; 33 size[block[i]]++; 34 if(!L[block[i]])L[block[i]]=i; 35 R[block[i]]=i; 36 } 37 sort(b+1,b+1+n); 38 int tot=unique(b+1,b+1+n)-b-1; 39 for(int i=1;i<=n;i++){ 40 a[i]=lower_bound(b+1,b+1+tot,a[i])-b; 41 } 42 // cout<<endl; 43 for(int i=1;i<=n;i++){ 44 add(block[i],a[i],1); 45 } 46 for(int i=n;i>=1;i--){ 47 add(0,a[i],1); 48 ans+=getsum(0,a[i]-1); 49 } 50 scanf("%d",&m); 51 printf("%d\n",ans); 52 for(int i=1;i<=m;i++){ 53 int x,y; 54 scanf("%d%d",&x,&y); 55 if(x>y)swap(x,y); 56 if(block[x]+1>=block[y]){ 57 for(int i=x+1;i<=y-1;i++){ 58 if(a[x]>a[i])ans--;if(a[x]<a[i])ans++; 59 if(a[y]<a[i])ans--;if(a[y]>a[i])ans++; 60 } 61 } 62 else{ 63 for(int i=block[x]+1;i<=block[y]-1;i++){ 64 ans-=getsum(i,a[x]-1)+size[i]-getsum(i,a[y]); 65 ans+=getsum(i,a[y]-1)+size[i]-getsum(i,a[x]); 66 } 67 for(int i=x+1;i<=R[block[x]];i++){ 68 if(a[x]>a[i])ans--;if(a[x]<a[i])ans++; 69 if(a[y]<a[i])ans--;if(a[y]>a[i])ans++; 70 } 71 for(int i=L[block[y]];i<=y-1;i++){ 72 if(a[x]>a[i])ans--;if(a[x]<a[i])ans++; 73 if(a[y]<a[i])ans--;if(a[y]>a[i])ans++; 74 } 75 } 76 if(a[x]>a[y])ans--; 77 if(a[x]<a[y])ans++; 78 add(block[x],a[x],-1);add(block[x],a[y],1); 79 add(block[y],a[y],-1);add(block[y],a[x],1); 80 swap(a[x],a[y]); 81 printf("%d\n",ans); 82 } 83 return 0; 84 }