zoukankan      html  css  js  c++  java
  • bzoj 3585 mex

    Written with StackEdit.

    题目描述

    有一个长度为(n)的数组({a_1,a_2,...,a_n})(m)次询问,每次询问一个区间内最小没有出现过的自然数。

    Input

    第一行(n,m)
    第二行为(n)个数。
    从第三行开始,每行一个询问(l,r)

    Output

    一行一个数,表示每个询问的答案。

    Sample Input

    5 5
    2 1 0 2 1
    3 3
    2 3
    2 4
    1 2
    3 5

    Sample Output

    1
    2
    3
    0
    3

    HINT

    对于(30\%)的数据:
    (1<=n,m<=1000.)

    对于(100\%)的数据:
    (1<=n,m<=200000,0<=ai<=10^9,1<=l<=r<=n.)

    Solution

    • 多个区间询问,可以离线,并且可以(O(1))转移,考虑使用莫队.
    • 但是(a_ileq 10^9),直接开个(cnt)数组记录当前区间内的各种个数似乎不可做?
    • 然而,对于大于(n)的元素,我们可以直接无视它.
    • 一方面,它一定不会成为答案,否则需要出现至少(0)~(n)(n+1)个数.
    • 另一方面,它肯定不会对答案做出贡献.否则答案也会大于(n),据上,不可能.
    • 所以(a_i)的范围只是虚张声势...我们处理时将大于(n)的数都视作(n+1)即可.
    • 然后就是一个愉快的莫队板子题了.
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LoveLive;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		{
    			fh=-1;
    			jp=getchar();
    		}
    	while (jp>='0'&&jp<='9')
    		{
    			out=out*10+jp-'0';
    			jp=getchar();
    		}
    	return out*fh;
    }
    const int MAXN=2e5+10;
    int cnt[MAXN];
    set<int> s;
    int Ans[MAXN];
    int n,m;
    int a[MAXN];
    int belong[MAXN],BlockSize;
    int L,R,res;
    struct Query{
    	int l,r;
    	int id;
    	bool operator < (const Query &rhs) const 
    		{
    			if(belong[l]!=belong[rhs.l])
    				return belong[l]<belong[rhs.l];
    			return belong[r]<belong[rhs.r];
    		}
    }q[MAXN];
    void BuildBlocks()
    {
    	BlockSize=sqrt(n);
    	for(int i=1;i<=n;++i)
    		belong[i]=(i/BlockSize)+1;
    }
    void add(int pos)
    {
    	++cnt[a[pos]];
    	for(int i=res;i<=n+2;++i)
    		if(cnt[i]==0)
    			{
    				res=i;
    				return;
    			}
    }
    void remove(int pos)
    {
    	--cnt[a[pos]];
    	if(cnt[a[pos]]==0)
    		res=min(res,a[pos]);
    }
    int main()
    {
    	n=read(),m=read();
    	for(int i=1;i<=n;++i)
    		a[i]=read(),a[i]=a[i]>n?n+1:a[i];
    	for(int i=1;i<=m;++i)
    		{
    			q[i].id=i;
    			q[i].l=read();
    			q[i].r=read();		
    		}
    	for(int i=0;i<=n;++i)
    		s.insert(i);
    	a[0]=n+2;
    	BuildBlocks();
    	sort(q+1,q+1+m);
    	L=0,R=0;
    	for(int i=1;i<=m;++i)
    		{
    			int l=q[i].l,r=q[i].r;
    			while(L<l)
    				remove(L),++L;
    			while(L>l)
    				--L,add(L);
    			while(R<r)
    				++R,add(R);
    			while(R>r)
    				remove(R),--R;
    			Ans[q[i].id]=res;
    		}
    	for(int i=1;i<=m;++i)
    		printf("%d
    ",Ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    纯JS制作选项卡--JavaScript实例集锦(初学)
    超级简单实用的CSS3动画,增添网页效果
    3种方法实现图片瀑布流的效果(纯JS,Jquery,CSS)
    CSS动画小结
    遗忘比死亡更可怕
    matplotlib笔记2
    matplotlib笔记1
    pandas数据结构之Panel笔记
    pandas数据结构之Series笔记
    ndarray笔记续
  • 原文地址:https://www.cnblogs.com/jklover/p/10105545.html
Copyright © 2011-2022 走看看