【清华集训2014】mex
2016-03-09 19:59
211 查看
Description
有一个长度为n的数组{a1,a2,…,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。Solution
一眼看过去,很明显就是数据结构。不过,用什么?怎么维护?
是个问题?
用什么
哎呀,发现很难找到一个可以在线的数据结构去维护。那么离线呢,好像离线可以。以下标线段树为节点的线段树,无法判重值,好像不能维护权值,想到不能维护权值,那么就有很多数据结构不能用了,维护权值的数据结构。有什么数据结构是维护下标的吗,最显然的,函数式线段树。
怎么维护
函数式线段树在这题,很明显是维护下标的了。离线打法好!既然我们要用离线,如果是从左到右的,输入l[i],r[i](询问l[i]到r[i]的区间)那么就是以r[i]为关键字从小到大排序。那么我们在函数式线段树的加入中就锁定了r[i]了。现在就很容易想了,比如说我现在要询问l到r中的答案,因为我们线段树的下标是权值,那么如果1到l的线段树中有一个下标是小于l的,那么答案就存在于这个区间(维护的是权值,越往左越小。下标小与l,那么肯定是l到r中没有的下标,而且肯定也没有这个值)。
那么很显然,我们维护的是在权值是l到r中出现过得最小下标。
Code
[code]#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define fo(i,a,b) for(i=a;i<=b;i++) const int maxn=200007; using namespace std; int i,j,k,l,n,m,ber; int a[maxn],ans[maxn]; struct nod{ int a,b,c; }b[maxn]; int t[maxn*3]; bool cmp(nod x,nod y){ return x.b<y.b; } void insert(int x,int l,int r,int y,int z){ if(l==r){ t[x]=z; } else{ int mid=(l+r)/2; if(y<=mid)insert(x*2,l,mid,y,z); else insert(x*2+1,mid+1,r,y,z); t[x]=min(t[x*2],t[x*2+1]); } } int get(int x,int l,int r,int z){ if(l==r) return l; int mid=(l+r)/2; if(t[x*2]<z) return get(x*2,l,mid,z); else return get(x*2+1,mid+1,r,z); } int main(){ scanf("%d%d",&n,&m); fo(i,1,n){ scanf("%d",&a[i]); if(a[i]>n+1)a[i]=n+1; } fo(i,1,m){ scanf("%d%d",&b[i].a,&b[i].b); b[i].c=i; } sort(b+1,b+1+m,cmp); ber=1; fo(i,1,n){ insert(1,0,n+1,a[i],i); fo(j,ber,m){ if(b[j].b>i){ ber=j; break; } ans[b[j].c]=get(1,0,n+1,b[j].a); } } fo(i,1,m) printf("%d\n",ans[i]); }
相关文章推荐
- 常见的dos命令
- 实现接口事件,在接口中实现事件
- 田渊栋:AlphaGo系统即使在单机上也有职业水平
- 阿里巴巴 一面
- WebView——重写WebView实现在WebView内部加载网页
- 浮点型数据存储方式
- 笔试面试搜集资料汇总
- android自学第三天
- struts动态方法调用之感叹号
- Spring整合CXF,发布RSETful 风格WebService
- hdu 5365
- Integer.highestOneBit(int i)的作用
- Java与C/C++的比较(转)
- HDU 3085 Nightmare Ⅱ 双向BFS
- 按照反向斜对角线(右上->左下)的方式打印M行N列的数组arrMatrix[M][N]
- MRC到ARC的自动转换
- 不用迭代器的容器表示
- win7出现无法连接到代理服务器的错误,不能上网的问题的解决
- The Worm Turns
- iOS黑魔法-Method Swizzling