BZOJ2141 排队(分块)
2015-06-02 23:51
471 查看
【题解】
分块,每块内部从小到大排序,每次询问,在完整的块内二分查找大于或小于 移动的值 的数的个数
复杂度:
初始求逆序对 O( n*sqrt(n) )
询问 O( m*sqrt(n) )
【代码】
分块,每块内部从小到大排序,每次询问,在完整的块内二分查找大于或小于 移动的值 的数的个数
复杂度:
初始求逆序对 O( n*sqrt(n) )
询问 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; }
相关文章推荐
- ci 笔记
- 冲刺Two之站立会议3
- ZooKeeper数据模型
- hdu 1541 Stars
- 数学之美
- LeetCode题解(13)--Roman to Integer
- Mysql数据库中设置root密码的命令及方法
- 《Arduino技术内幕》学习笔记(一)
- 简介nandflash、norflash、ram、sram、dram、rom、eeprom、flash的区别
- JAVA邮件发送的简单实现
- go学习笔记:1.1变量
- 如何使程序脱离终端在后台运行
- linux 系统学习
- node-主从模式
- [LeetCode] Sort List
- @NotFound解决关联外键数据不存在时抛出异常的问题
- Part 72 to 81 Talking about Dictionary and List collection in C#
- 国嵌内核驱动进阶班-7-1(Ioctl设备控制)
- HTML5
- norflash与nandflash芯片内执行(XIP)