bzoj 3585: mex

3585: mex

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 969  Solved: 511
[Submit][Status][Discuss]

Description

  有一个长度为n的数组{a1,a2,...,an}。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

数据规模和约定

  对于100%的数据:

  1<=n,m<=200000

  0<=ai<=109

  1<=l<=r<=n

  对于30%的数据:

  1<=n,m<=1000

以权值为下标,

minn[i]=j,表示i所代表的权值为[l,r]的区间,最早出现的位置为j

例:0 2 1 0 1 3 2

对于root[7]来说,

[0,3]=1, 0最早出现在第1个位置

[1,3]=2, 2最早出现在第2个位置

查询[l,r]时,在root[r]里查询

如果左子区间的minn>=l,说明权值小的左边一半都最早出现在l以后,就往右孩子找

否则,说明权值小的左边一半有没有出现在l之后的,就往左孩子找

因为是在root[r]里,所以保证不超过右边界

对于10^9的权值,离散化?

不。

如果权值>n,直接让它=n

因为此时<n中一定有没有出现的数

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 200001
using namespace std;
int n,q,tot;
int root[N],minn[N*20];

    int lc[N*20],rc[N*20];
    void change(int &now,int pre,int l,int r,int pos,int val)
    {
        if(!now) now=++tot;
        if(l==r)
        {
            minn[now]=val;
            return;
        }
        int mid=l+r>>1;
        if(pos<=mid)
        {
            change(lc[now],lc[pre],l,mid,pos,val);
            rc[now]=rc[pre];
        }
        else
        {
            change(rc[now],rc[pre],mid+1,r,pos,val);
            lc[now]=lc[pre];
        }
        minn[now]=min(minn[lc[now]],minn[rc[now]]);
    }
    int query(int now,int l,int r,int pos)
    {
        if(l==r) return l;
        int mid=l+r>>1;
        if(minn[lc[now]]>=pos) return query(rc[now],mid+1,r,pos);
        return query(lc[now],l,mid,pos);
    }

int main()
{
    freopen("mex.in","r",stdin);
    freopen("mex.out","w",stdout);
    int m;
    scanf("%d%d",&n,&m);
    int x;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        if(x>n) x=n;
        change(root[i],root[i-1],0,n,x,i);
    }
    int l,r;
    while(m--)
    {
        scanf("%d%d",&l,&r);
        printf("%d\n",query(root[r],0,n,l));
    }
}
时间: 2024-11-07 00:34:22

bzoj 3585: mex的相关文章

[BZOJ 3585] mex 【莫队+分块】

题目链接:BZOJ - 3585 题目分析 区间mex,即区间中没有出现的最小自然数. 那么我们使用一种莫队+分块的做法,使用莫队维护当前区间的每个数字的出现次数. 然后求mex用分块,将权值分块(显然mex 一定小于等于 n ,大于 n 的权值没有意义,可以直接忽略),每块大小 sqrt(n) . 然后区间中的某个数的数量被减到0的时候就将它所在的块的种类计数减一,添加数的时候类似. 然后枚举每个块,找到最小的中间有数不存在的块(即种类数小于块中的数的种数),然后到这个快里直接从小一个一个找到

bzoj 3585: mex &amp;&amp; 3339: Rmq Problem -- 主席树

3585: mex Time Limit: 20 Sec  Memory Limit: 128 MB Description 有一个长度为n的数组{a1,a2,...,an}.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

BZOJ - 3339: Rmq BZOJ - 3585: mex

3339: Rmq Problem 3585: mex 题解:分块维护权值,用莫队转移. 分块修改操作$O(1)$,查询$O(\sqrt{A_{max}})$.莫队转移$O(m\sqrt n)$.总共是$O(m\sqrt n)$ 一份代码解决两道题.额外的经验! 1 #include<cmath> 2 #include<algorithm> 3 #include<cstdio> 4 #include<iostream> 5 using namespace s

BZOJ 3585 mex 莫队算法+分块

题目大意:给定一个长度为n的数组,m次询问某个区间内的mex值 怒写莫队233 将权值分成√n块,记录每个权值的出现次数以及每块内有多少权值出现过 修改O(1)即可完成 查询时首先扫一遍找到第一个块内有没有覆盖的点的块 然后在块内暴力查找 时间复杂度O(√n) 套个莫队 总时间复杂度O(m√n) #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include

BZOJ.3585.mex(线段树)

题目链接 考虑\([1,i]\)的\(mex[i]\),显然是单调的 而对于\([l,r]\)与\([l+1,r]\),如果\(nxt[a[l]]>r\),那么\([l+1,r]\)中所有\(>a[l]\)的数显然要改成\(a[l]\) 询问排序,离散化,预处理下nxt[],剩下就是线段树的区间更新.查询了 /* 离散化的时候>=n的全部看做n就好了 查询时是只需查r点的(l之前能更新r的已经更新完了,初始时是[1,r],r点现在就是[l,r]了) 单点即可不需要PushUp(也不好得某

【BZOJ】3339: Rmq Problem &amp; 3585: mex(线段树+特殊的技巧)

http://www.lydsy.com/JudgeOnline/problem.php?id=3585 好神的题. 但是!!!!!!!!!!!!!!我线段树现在要开8倍空间才能过!!!!!!!!!!这什么梗...................... 我思考了很久空间的问题,因为我在pushdown的时候可能会越界,或许是pushup? 不管了.然后看了zyf的写法.看来以后得注意下...pushdown弄成先放了... 本题的做法: 好神orz 首先像莫队一样离线区间,左端点在前. 考虑如何

BZOJ 3339 &amp;&amp; BZOJ 3585 莫队+权值分块

显然若一个数大于n就不可能是答案. 1 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <algorithm> 6 #include <map> 7 #include <cmath> 8 using namespace std; 9 const int Maxn=200010; 10 struct Info{int l,r,Id;}P[

12月刷题总结

各种被屠...学东西各种慢... QAQ 字符串: sam: [SPOJ]7258. Lexicographical Substring Search(后缀自动机) [SPOJ]1812. Longest Common Substring II(后缀自动机) [BZOJ]2555: SubString(后缀自动机) [BZOJ]3172: [Tjoi2013]单词(后缀自动机) [wikioi]3160 最长公共子串(后缀自动机) lcp: [BZOJ]1014: [JSOI2008]火星人pr

bzoj3585 mex

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3585 [题解] 哎好像就是上题啊 怎么权值是1e9了啊 那没关系啊把主席树调成[0,1e9]的就行啦 哎调调空间 过了 # include <stdio.h> # include <string.h> # include <algorithm> // # include <bits/stdc++.h> using namespace std; type