BZOJ 3585 mex 莫队算法+分块
来源:互联网 发布:mac桌面路径命令 编辑:程序博客网 时间:2024/06/04 18:02
BZOJ 3585 mex
题目链接:右转进入题目
题目大意:给定n,m,n个数(0<=ai<=1e9),m个询问;
每次询问一段区间[L,R],在aL,a(L+1),,,,aR中第一个没有出现的自然数是多少?
n,m<=200010
题解:
裸的莫队算法。
但是这个题有一些值得注意的地方:
第零,由于莫队算法有nsqrt(n)次修改,m次询问,n和m同阶。
可以看到修改次数比询问次数多得多。
辣么说如果用线段树的话,修改和询问都是O(lng)的,那么复杂度就是O(n*sqrt(n)*lgn)的,会TLE。
所以改用分块。尽管询问是O(sqrt(n))的,但是修改是O(1)的。
因此改用分块就变成了O(n*sqrt(n))。就不会TLE了。
分块的做法是从第一块开始扫,扫到第一块不是每个点都是1的块,在块内暴力检查。
复杂度显然是O(sqrt(n))的。
第一,虽然ai<=1e9,但是没有离散化的必要。更准确的说,对于>n的数字可以忽视。
因为>n的数字一定不会成为答案(想一想,为什么)。
一开始我还想离散化发现怎么也想不对,看了大神的blog才明白【捂脸
第二,绝大多数人下意识的当成了正整数,所以分块的时候就没有考虑0的情况。
但事实上有两种解决方法不需要重写,要么求mex的时候直接看一下a[0]的值,要么把读入的所有n个数字+1,最后查询得到的答案-1即可。
代码里用的前者。
附上代码:
//BZOJ 3585#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<cmath>#include<vector>#define MAXN 200010#define MAXM 200010#define BLOCK_CNT 500using namespace std;int n,m,cnt[MAXN],a[MAXN];struct block{private:int val[MAXN],belong[MAXN],sz,cnt,n;int L[BLOCK_CNT],R[BLOCK_CNT],sumn[BLOCK_CNT];public:void init(int _n){sz=sqrt(_n+0.5);n=_n;cnt=n/sz+1;belong[0]=0;for(int i=1;i<=n;i++)belong[i]=(i-1)/sz+1;for(int i=1;i<=cnt;i++)L[i]=(i-1)*sz+1,R[i]=i*sz;}void update(int pos,int v){sumn[belong[pos]]+=v;val[pos]+=v;}int mex(){if(val[0]==0) return 0;int cur=1;while(cur<=cnt&&sumn[cur]==sz) cur++;for(int i=L[cur];i<=R[cur];i++)if(val[i]==0) return i;return 0;}}b;struct query{int l,r,id,pos;}q[MAXM];bool cmp(const query &q1,const query &q2){if(q1.pos==q2.pos) return q1.r<q2.r;else return q1.pos<q2.pos;}int ans[MAXM];void add(int x){if(a[x]>=n) return;if(cnt[a[x]]==0) b.update(a[x],1);cnt[a[x]]++;}void del(int x){if(a[x]>=n) return;cnt[a[x]]--;if(cnt[a[x]]==0) b.update(a[x],-1);}int main(){scanf("%d%d",&n,&m);int sz;sz=sqrt(n+0.5);b.init(n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);for(int i=1;i<=m;i++){scanf("%d%d",&q[i].l,&q[i].r);q[i].id=i;q[i].pos=q[i].l/sz;}sort(q+1,q+m+1,cmp);int L=1,R=0;for(int i=1;i<=m;i++){while(L<q[i].l) del(L++);while(L>q[i].l) add(--L);while(R<q[i].r) add(++R);while(R>q[i].r) del(R--);ans[q[i].id]=b.mex();}for(int i=1;i<=m;i++)printf("%d\n",ans[i]);return 0;}
0 0
- BZOJ 3585 mex 莫队算法+分块
- BZOJ 3585 mex 莫队算法+分块
- BZOJ 3585 mex 莫队算法+分块
- BZOJ 3585: mex|莫队算法
- 【bzoj3585】mex 分块+莫队算法
- bzoj3585 mex 分块+莫队算法
- BZOJ 3339/3585 Rmq Problem/mex 莫队算法
- jzoj 3547. 【清华集训2014】mex 分块+莫队算法
- bzoj 3781: 小B的询问 莫队算法+分块
- bzoj 3236: [Ahoi2013]作业 莫队算法+分块
- BZOJ-3757 苹果树 LCA 莫队算法 树分块
- bzoj 3585: mex
- bzoj-3585 mex
- [BZOJ 3585]mex
- bzoj 3585: mex
- bzoj 3585: mex
- BZOJ 3585 mex
- 分块、莫队算法
- android studio 开发的项目文件太大, 已经超过1个G了!
- ASP怎么实现不同页面不同meta
- 年轻人就该大胆在一线城市闯
- 2017.3.19
- 冒泡排序算法
- BZOJ 3585 mex 莫队算法+分块
- IDEA中Maven项目无法创建包
- 未来宝宝照片合成,怎么做到的呢?
- python数据挖掘课程 十.Pandas、Matplotlib、PCA绘图实用代码补充
- Codeforces-----614A---Link/Cut Tree---数学水题
- Maximum Subarray
- 乐高 ev3 数硬币机
- php 里一个sql语句太长,调式时发现sql语句变得不完整了
- ios的tableview的cell