BZOJ2038 [2009国家集训队]小Z的袜子(hose)(莫队算法)
2016-02-29 10:41
357 查看
神奇的莫队算法,用来解决可离线无修改的区间查询问题:
首先对原序列进行分块,√n块每块√n个;
然后对所有查询的区间[l,r]进行排序,首先按l所在的块序号升序排序,如果一样就按r升序排序;
最后就按顺序一个一个求出各个查询的结果:知道[l,r]的答案,并且在此基础上能在比较快地在O(x)得到相邻区间[l+1,r]、[l-1,r]、[l,r-1]、[l,r+1]的答案,那样就能从[l,r]的基础上对lr加加减减得到任意一个区间[l',r']的答案。
看似暴力,但这样做的时间复杂度是O(x*n*√n) !因为:
l是按其所在块序号排列,同一块里面一次最多√n次++l或--l到达目标;一块最多大概√n次加加减减;总共√n块;所以l改变的次数顶多也就√n*√n*√n。
r在同一块是升序的,所以同一块最多n次++r;下一块时r假设在上一块到达最远,那最多n次--r回到目标;总共√n块;所以r改变次数顶多也就(n+n)*√n。
而每次加加减减转移新答案的代价是x,所以时间复杂度是O(x*n*√n) !
这一题,设每个区间[l,r]各个颜色的袜子数分别为$a,b,c,d,\dots$,每个区间[l,r]的答案就是$(C_a^2+C_b^2+C_c^2+C_d^2+\cdots)/C_{r-l+1}^2$,展开化简得:
$$(a^2+b^2+c^2+d^2+\cdots-a-b-c-d-\cdots)/((r-l+1)*(r-l+1-1))$$
$$(a^2+b^2+c^2+d^2+\cdots-(r-l+1))/((r-l+1)*(r-l))$$
其中$(a^2+b^2+c^2+d^2+\cdots)$便可作为莫队算法处理的区间答案,开个数组记录abcd...的个数可以在O(1)转移到相邻区间。
另外特判区间l=r的情况。。
首先对原序列进行分块,√n块每块√n个;
然后对所有查询的区间[l,r]进行排序,首先按l所在的块序号升序排序,如果一样就按r升序排序;
最后就按顺序一个一个求出各个查询的结果:知道[l,r]的答案,并且在此基础上能在比较快地在O(x)得到相邻区间[l+1,r]、[l-1,r]、[l,r-1]、[l,r+1]的答案,那样就能从[l,r]的基础上对lr加加减减得到任意一个区间[l',r']的答案。
看似暴力,但这样做的时间复杂度是O(x*n*√n) !因为:
l是按其所在块序号排列,同一块里面一次最多√n次++l或--l到达目标;一块最多大概√n次加加减减;总共√n块;所以l改变的次数顶多也就√n*√n*√n。
r在同一块是升序的,所以同一块最多n次++r;下一块时r假设在上一块到达最远,那最多n次--r回到目标;总共√n块;所以r改变次数顶多也就(n+n)*√n。
而每次加加减减转移新答案的代价是x,所以时间复杂度是O(x*n*√n) !
这一题,设每个区间[l,r]各个颜色的袜子数分别为$a,b,c,d,\dots$,每个区间[l,r]的答案就是$(C_a^2+C_b^2+C_c^2+C_d^2+\cdots)/C_{r-l+1}^2$,展开化简得:
$$(a^2+b^2+c^2+d^2+\cdots-a-b-c-d-\cdots)/((r-l+1)*(r-l+1-1))$$
$$(a^2+b^2+c^2+d^2+\cdots-(r-l+1))/((r-l+1)*(r-l))$$
其中$(a^2+b^2+c^2+d^2+\cdots)$便可作为莫队算法处理的区间答案,开个数组记录abcd...的个数可以在O(1)转移到相邻区间。
另外特判区间l=r的情况。。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define MAXN 55555 int block; struct Query{ int i,l,r; bool operator<(const Query &q)const{ if(l/block==q.l/block) return r<q.r; return l/block<q.l/block; } }query[MAXN]; long long gcd(long long a,long long b){ if(b==0) return a; return gcd(b,a%b); } int seq[MAXN]; long long cnt[MAXN],ansx[MAXN],ansy[MAXN]; void insert(long long &res,int a){ res-=cnt[a]*cnt[a]; ++cnt[a]; res+=cnt[a]*cnt[a]; } void remove(long long &res,int a){ res-=cnt[a]*cnt[a]; --cnt[a]; res+=cnt[a]*cnt[a]; } int main(){ int n,m; scanf("%d%d",&n,&m); block=sqrt(n); for(int i=1; i<=n; ++i) scanf("%d",seq+i); for(int i=0; i<m; ++i){ query[i].i=i; scanf("%d%d",&query[i].l,&query[i].r); } sort(query,query+m); int l=1,r=1; ++cnt[seq[1]]; long long res=1; for(int i=0; i<m; ++i){ if(query[i].l==query[i].r){ ansx[query[i].i]=0; ansy[query[i].i]=1; continue; } while(l<query[i].l){ remove(res,seq[l]); ++l; } while(l>query[i].l){ --l; insert(res,seq[l]); } while(r<query[i].r){ ++r; insert(res,seq[r]); } while(r>query[i].r){ remove(res,seq[r]); --r; } long long a=res-(query[i].r-query[i].l+1),b=(query[i].r-query[i].l+1LL)*(query[i].r-query[i].l),c=gcd(b,a); ansx[query[i].i]=a/c; ansy[query[i].i]=b/c; } for(int i=0; i<m; ++i) printf("%lld/%lld\n",ansx[i],ansy[i]); return 0; }
相关文章推荐
- bootsrap判断checkbox选择的个数
- 201601读书分享——《微创新》
- 面向对象的勾勾画画
- BZOJ1061[Noi2008] 志愿者招募
- Android优化——UI优化(五) Listview 重用convertView
- iOS开发文件夹--Copy items if needed
- android 调用系统相机拍照 获取原图
- 流行的Go语言web框架简介
- 【Linux】linux常用基本命令
- 如何降低人员流失造成对项目进度的影响
- DataTbale分页显示
- JAVA泛型的基本使用
- Android Material Design之CoordinatorLayout+AppBarLayout实现上滑隐藏ToolBar
- R.swift:以一种优雅安全的方式使用资源文件
- JPA基础思路
- 让IE6 IE7 IE8 IE9 IE10 IE11支持Bootstrap的解决方法
- 第五十一篇:LBP 解释
- 状态压缩动态规划入门
- SAS Timeseries Modelling
- tomcat架构分析(valve机制)