题目链接


题意:多次求区间\(mex\)。

考虑\([1,i]\)的\(mex[i]\),显然是单调的

而对于\([l,r]\)与\([l+1,r]\),如果\(nxt[a[l]]>r\),那么\([l+1,r]\)中所有\(>a[l]\)的数显然要改成\(a[l]\)

把询问按左端点排序;离散化,预处理下\(nxt[]\),处理出\([1,i]\)的\(mex[i]\)。剩下就是线段树的区间更新、单点查询了

  1. /*
  2. 离散化的时候>=n的全部看做n就好了
  3. 查询时是只需查r点的(l之前能更新r的已经更新完了,初始时是[1,r],r点现在就是[l,r]了)
  4. 单点即可不需要PushUp(也不好得某个区间的mex)
  5. 非叶节点上的mex完全可以代替tag
  6. 离散化需要注意 其实不是很懂这
  7. */
  8. #include<cstdio>
  9. #include<cctype>
  10. #include<algorithm>
  11. #define gc() getchar()
  12. #define now node[rt]
  13. #define lson node[node[rt].ls]
  14. #define rson node[node[rt].rs]
  15. const int N=2e5+5,INF=1e7;
  16. int n,m,A[N],mex[N]/*不要和A混用*/,tmp[N],nxt[N],las[N],ans[N];
  17. bool vis[N];
  18. struct Ques
  19. {
  20. int l,r,id;
  21. Ques() {}
  22. Ques(int l,int r,int id): l(l),r(r),id(id) {}
  23. bool operator <(const Ques &x)const {return l<x.l;}
  24. }q[N];
  25. struct Seg_Tree
  26. {
  27. int tot;
  28. struct Node
  29. {
  30. int ls,rs,mex;
  31. }node[N<<1];
  32. inline void Upd(int &x,int v) {x=std::min(x,v);}
  33. inline void PushDown(int rt)
  34. {
  35. Upd(lson.mex,now.mex), Upd(rson.mex,now.mex);
  36. now.mex=INF;
  37. }
  38. void Build(int l,int r)
  39. {
  40. int rt=tot++;
  41. if(l==r) now.mex = mex[l];
  42. else
  43. {
  44. int m=l+r>>1; now.mex=INF;
  45. now.ls=tot, Build(l,m);
  46. now.rs=tot, Build(m+1,r);
  47. }
  48. }
  49. void Update(int l,int r,int rt,int L,int R,int v)
  50. {
  51. if(L<=l && r<=R) Upd(now.mex,v);
  52. else
  53. {
  54. if(now.mex<INF) PushDown(rt);
  55. int m=l+r>>1;
  56. if(L<=m) Update(l,m,now.ls,L,R,v);
  57. if(m<R) Update(m+1,r,now.rs,L,R,v);
  58. }
  59. }
  60. int Query(int l,int r,int rt,int p)
  61. {
  62. if(l==r) return now.mex;
  63. if(now.mex<INF) PushDown(rt);
  64. int m=l+r>>1;
  65. if(p<=m) return Query(l,m,now.ls,p);
  66. else return Query(m+1,r,now.rs,p);
  67. }
  68. }t;
  69. #undef now
  70. inline int read()
  71. {
  72. int now=0,f=1;register char c=gc();
  73. for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
  74. for(;isdigit(c);now=now*10+c-'0',c=gc());
  75. return now*f;
  76. }
  77. int Find(int x,int r)
  78. {
  79. int l=1,m;
  80. while(l<r)
  81. {
  82. if(tmp[(m=l+r>>1)]<x) l=m+1;
  83. else r=m;
  84. }
  85. return l;
  86. }
  87. int main()
  88. {
  89. n=read(),m=read();
  90. for(int i=1; i<=n; ++i) tmp[i]=A[i]=std::min(n,read());
  91. std::sort(tmp+1,tmp+1+n);
  92. int cnt=1;
  93. for(int i=2; i<=n && !(tmp[i]==n&&tmp[i+1]==n); ++i)
  94. if(tmp[i]!=tmp[i-1]) tmp[++cnt]=tmp[i];
  95. for(int k=0,p,i=1; i<=n; ++i)
  96. {
  97. vis[p=Find(A[i],cnt)]=1;
  98. if(A[i]==k)//只有在当前最小值出现时才更新。。mex...
  99. while(vis[p])//p-1,vis[k]?
  100. {
  101. ++k;
  102. if(tmp[++p]!=k) break;//离散化后
  103. }
  104. mex[i]=k;
  105. }
  106. t.Build(1,n);
  107. for(int i=0; i<=n; ++i) las[i]=n+1;
  108. for(int tp,i=n; i; --i) nxt[i]=las[tp=Find(A[i],cnt)], las[tp]=i;//!
  109. for(int l,i=1; i<=m; ++i) l=read(), q[i]=Ques(l,read(),i);
  110. std::sort(q+1,q+1+m);
  111. for(int now=1,i=1; i<=m; ++i)
  112. {
  113. while(now<q[i].l)
  114. t.Update(1,n,0,now+1,nxt[now]-1,A[now]), ++now;
  115. ans[q[i].id]=t.Query(1,n,0,q[i].r);
  116. }
  117. for(int i=1; i<=m; ++i) printf("%d\n",ans[i]);
  118. return 0;
  119. }

BZOJ.3585.mex(线段树)的更多相关文章

  1. bzoj 3585 mex - 线段树 - 分块 - 莫队算法

    Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问 ...

  2. BZOJ 3585: mex [主席树]

    3585: mex Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 787  Solved: 422[Submit][Status][Discuss] ...

  3. BZOJ.4184.shallot(线段树分治 线性基)

    BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...

  4. [BZOJ 4025]二分图(线段树分治+带边权并查集)

    [BZOJ 4025]二分图(线段树分治+带边权并查集) 题面 给出一个n个点m条边的图,每条边会在时间s到t出现,问每个时间的图是否为一个二分图 \(n,m,\max(t_i) \leq 10^5\ ...

  5. 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex

    题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...

  6. BZOJ 3585: mex( 离线 + 线段树 )

    离线, 询问排序. 先处理出1~i的答案, 这样可以回答左端点为1的询问.完成后就用seq(1)将1到它下一次出现的位置前更新. 不断这样转移就OK了 ------------------------ ...

  7. bzoj 3585: mex && 3339: Rmq Problem -- 主席树

    3585: mex Time Limit: 20 Sec  Memory Limit: 128 MB Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区 ...

  8. HDU-4747 Mex 线段树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4747 题意:求一个数列中,所有mex(L,R)的和. 注意到mex是单调不降的,那么首先预处理出mex ...

  9. 【BZOJ 3476】 线段树===

    59  懒惰的奶牛贝西所在的牧场,散落着 N 堆牧草,其中第 i 堆牧草在 ( Xi,Yi ) 的位置,数量有 Ai 个单位.贝西从家移动到某一堆牧草的时候,只能沿坐标轴朝正北.正东.正西.正南这四个 ...

随机推荐

  1. mysql系列一、mysql数据库规范

    一. 表设计 库名.表名.字段名必须使用小写字母,“_”分割. 库名.表名.字段名必须不超过12个字符. 库名.表名.字段名见名知意,建议使用名词而不是动词. 表必须使用InnoDB存储引擎. 表必须 ...

  2. HTML学习笔记03-HTML基础

    <!DOCTYPE HTML> <html> <head> <title> </title> </head> <body& ...

  3. java工程操作redis

    启动redis服务 redis-server redis.windows.conf 添加驱动 <dependency> <groupId>redis.clients</g ...

  4. nginx报错:403 Forbidden 并且访问首页index.php是下载文件的状态

    nginx报错:403 Forbidden 并且访问首页index.php是下载文件的状态,不能正常解析php 系统有其他两个站访问是正常的 看日志没有看到明显的错误 搜索了下: 答案如下: php的 ...

  5. mac安装RabbitMQ

    1 下载 地址 http://www.rabbitmq.com/install-standalone-mac.html 2 rabbitmq的安装目录: /Users/ysyc1/rabbitmq_s ...

  6. javascript this详解(转)

    在面向对象编程语言中,对于this关键字我们是非常熟悉的.比如C++.C#和Java等都提供了这个关键字,虽然在开始学习的时候觉得比较难,但只要理解了,用起来是非常方便和意义确定的.JavaScrip ...

  7. 深度学习Bible学习笔记:第一章 前言

    写在前面:请务必踏踏实实看书,结合笔记或视频来理解学习,任何技术,啃砖头是最扎实最系统的,为避免知识碎片化,切忌抛却书本的学习!!! 一 什么是深度学习 1 关于AI: AI系统必须具备从原始数据提取 ...

  8. 使用exundelete在Linux下恢复删除的文件

    原文:https://my.oschina.net/looly/blog/261912 Linux下执行 rm 并不会真正删除,而是将inode节点中的扇区删除,同时释放数据块.在数据块被系统重新分配 ...

  9. python 全栈开发,Day21(抽象类,接口类,多态,鸭子类型)

    一.昨日复习 派生方法和派生属性 super 只有在子父类拥有同名方法的时候, 想使用子类的对象调用父类的方法时,才使用super super在类内 : super().方法名(arg1,..) 指名 ...

  10. 集合List和ArrayList的示例

    package chapter09; import java.util.ArrayList;import java.util.List; /* * List * ArrayList底层是数组 * 特点 ...