[BZOJ3339]Rmq Problem / mex
Description:
有一个长度为n的数组{a1,a2,…,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。
Hint:
\(n \le 2*10^5\)
Solution:
主席树好题,回滚莫队板子题?
把坐标离散化
不同于维护\(size\),这里用线段树维护以一个区间所有数的最后出现位置的最小值
这样我们每次直接在以\(r\)为根的值域线段树上找最小的\(val<l\)的数
// luogu-judger-enable-o2
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int mxn=8e6+100,mxm=1e7+5;
int n,m,s,p,cnt,tot,a[mxn],b[mxn],rt[mxm],tr[mxm],ls[mxm],rs[mxn];
inline int read() {
char c=getchar(); int x=0,f=1;
while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
return x*f;
}
inline int chkmax(int &x,int y) {if(x<y) x=y;}
inline int chkmin(int &x,int y) {if(x>y) x=y;}
struct ed {
int to,nxt;
}t[mxn<<1];
void update(int las,int &p,int l,int r,int val,int pos)
{
if(!p) p=++cnt;
if(l==r) {tr[p]=val;return ;} int mid=(l+r)>>1;
if(pos<=mid) update(ls[las],ls[p],l,mid,val,pos),rs[p]=rs[las];
else update(rs[las],rs[p],mid+1,r,val,pos),ls[p]=ls[las];
tr[p]=min(tr[ls[p]],tr[rs[p]]);
}
int query(int p,int l,int r,int pos)
{
if((p == 0) or (l==r)) return b[l];
int mid=(l+r)>>1;
if(tr[ls[p]]>=pos) return query(rs[p],mid+1,r,pos);
else return query(ls[p],l,mid,pos);
}
int main()
{
n=read(); m=read(); int l,r; b[++tot]=0;
for(int i=1;i<=n;++i) a[i]=read(),b[++tot]=a[i],b[++tot]=a[i]+1;
sort(b+1,b+tot+1); s=unique(b+1,b+tot+1)-b-1;
for(int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+s+1,a[i])-b;
for(int i=1;i<=n;++i) update(rt[i-1],rt[i],1,s,i,a[i]);
for(int i=1;i<=m;++i) {
l=read(); r=read();
printf("%d\n",query(rt[r],1,s,l));
}
return 0;
}
常数极大的回滚莫队:
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
const int mxn=5e5+5;
int n,m,L,R,sz,num,res,a[mxn],b[mxn],bl[mxn],ans[mxn],bac[mxn];
inline int read() {
char c=getchar(); int x=0,f=1;
while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
return x*f;
}
inline int chkmax(int &x,int y) {if(x<y) x=y;}
inline int chkmin(int &x,int y) {if(x>y) x=y;}
struct ed {
int to,nxt;
}t[mxn<<1];
struct Q {
int id,l,r;
}q[mxn];
int cmp(Q x,Q y) {
return bl[x.l]==bl[y.l]?x.r>y.r:bl[x.l]<bl[y.l];
}
void md(int x) {
if(a[x]<=n) {
--bac[a[x]];
if(bac[a[x]]==0) chkmin(res,a[x]);
}
}
void solve()
{
int l=1,r=0,z=1;
for(int i=1;i<=num;++i) {
L=(i-1)*sz; R=i*sz+1; res=n+1;
for(int j=0;j<=n;++j) bac[j]=0;
for(int j=1;j<=n;++j) if(a[j]<=n) ++bac[a[j]];
for(int j=0;j<=n;++j) if(!bac[j]) {res=j;break;}
l=-1,r=n+1; while(l<L-1) md(++l);
for(;bl[q[z].l]==i;++z) {
if(bl[q[z].l]==bl[q[z].r]) {
for(int k=q[z].l;k<=q[z].r;++k)
if(a[k]<=n) ++b[a[k]];
for(int k=0;k<=n;++k)
if(!b[k]) {ans[q[z].id]=k;break;}
for(int k=q[z].l;k<=q[z].r;++k)
if(a[k]<=n) --b[a[k]];
continue ;
}
while(r-1>q[z].r) md(--r); int las=res;
while(l<q[z].l-1) md(++l);
while(l>=L) {if(a[l]<=n) ++bac[a[l]]; --l;}
ans[q[z].id]=res; res=las;
}
}
}
int main()
{
n=read(); m=read(); sz=sqrt(n); int l,r; a[0]=n+1;
for(int i=1;i<=n;++i)
a[i]=read(),bl[i]=(i-1)/sz+1,chkmax(num,bl[i]);
for(int i=1;i<=m;++i)
q[i].l=read(),q[i].r=read(),q[i].id=i;
sort(q+1,q+m+1,cmp); solve();
for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
return 0;
}
[BZOJ3339]Rmq Problem / mex的更多相关文章
- 分块+莫队||BZOJ3339||BZOJ3585||Luogu4137||Rmq Problem / mex
题面:P4137 Rmq Problem / mex 题解:先莫队排序一波,然后对权值进行分块,找出第一个没有填满的块,直接for一遍找答案. 除了bzoj3339以外,另外两道题Ai范围都是1e9. ...
- BZOJ3339&&3585 Rmq Problem&&mex
BZOJ3339&&3585:Rmq Problem&&mex Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最 ...
- 【Luogu4137】Rmq Problem/mex (莫队)
[Luogu4137]Rmq Problem/mex (莫队) 题面 洛谷 题解 裸的莫队 暴力跳\(ans\)就能\(AC\) 考虑复杂度有保证的做法 每次计算的时候把数字按照大小也分块 每次就枚举 ...
- P4137 Rmq Problem / mex (莫队)
题目 P4137 Rmq Problem / mex 解析 莫队算法维护mex, 往里添加数的时候,若添加的数等于\(mex\),\(mex\)就不能等于这个值了,就从这个数开始枚举找\(mex\): ...
- 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex
题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...
- 洛谷 P4137 Rmq Problem /mex 解题报告
P4137 Rmq Problem /mex 题意 给一个长为\(n(\le 10^5)\)的数列\(\{a\}\),有\(m(\le 10^5)\)个询问,每次询问区间的\(mex\) 可以莫队然后 ...
- BZOJ 3339 && luogu4137 Rmq Problem / mex(莫队)
P4137 Rmq Problem / mex 题目描述 有一个长度为n的数组{a1,a2,-,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. 输入输出格式 输入格式: 第一行n,m. ...
- [bzoj3585] Rmq Problem / mex
[bzoj3585] Rmq Problem / mex bzoj luogu 看上一篇博客吧,看完了这个也顺理成章会了( (没错这篇博客就是这么水) #include<cstdio> # ...
- [bzoj3339]Rmq Problem||[bzoj3585]mex_线段树
Rmq Problem bzoj-3339||mex bzoj-3585 题目大意:给定一个长度为n的数列a,多次讯问区间l,r中最小的不属于集合{$A_l,A_{l+1}...A_r$}的非负整数. ...
随机推荐
- Windows Internals 笔记——错误处理
1.Windows函数检测到错误时,会使用一种名为“线程本地存储区”的机制将相应的错误代码与“主调线程”关联到一起.这种机制使得不同的线程能独立运行,不会出现相互干扰对方的错误代码的情况. 2.Get ...
- WPF应用程序内存泄漏的一些原因
原文:Finding Memory Leaks in WPF-based applications There are numbers of blogs that folks wrote about ...
- 'tensorflow' has no attribute 'sub'
在学习tensorflow的时候,照到官方的例子做,发现了一个 Traceback (most recent call last): File , in <module> sub = tf ...
- OpenJDK-study-002 从GitHub下载openjdk,以及Cygwin的安装
承前启后 由于上一篇openjdk-study-001中,从Mercurial直接拉取openjdk森林失败,于是网上搜了一下,发现GitHub上有人分享openjdk的源码 https://gith ...
- [转] webpack之前端性能优化(史上最全,不断更新中。。。)
最近在用webpack优化首屏加载性能,通过几种插件之后我们上线前后的速度快了一倍,在此就简单的分享下吧,先上个优化前后首屏渲染的对比图. 可以看到总下载时间从3800ms缩短到1600ms. 我们在 ...
- POJ 1364 / HDU 3666 【差分约束-SPFA】
POJ 1364 题解:最短路式子:d[v]<=d[u]+w 式子1:sum[a+b+1]−sum[a]>c — sum[a]<=sum[a+b+1]−c−1 ...
- js/jquery如何获取获取父窗口的元素
1.$("#父窗口元素ID",window.parent.document); 对应javascript版本为 window.parent.document.getElementB ...
- [arc066f]Contest with Drinks Hard
题目大意: 有一些物品,每个买了有代价. 如果存在一个极大区间[l,r]内的物品都被买了,这个区间长度为k,可以获得的收益是k*(k+1)/2. 现在若干次询问,每次问假如修改了某个物品的价格,最大收 ...
- cookie实现刷新不变化树形菜单
通过设置cookie来保存树形菜单的状态,在页面加载时重新读取cookie来设置菜单. 菜单的HTML结构: <div class="treemenu"> <ul ...
- 【转】PropertyGrid控件中的多级显示
运行效果: 解决方案: MainForm.cs public partial class MainForm : Form { public MainForm() { InitializeCompone ...