题意

给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大。如果找不到这样的数,则直接输出0。我会采取一些措施强制在线。

分析

预处理出pre[i],nxt[i]分别代表左边离它最近的相同数字的坐标,nxt[i]代表右边离它最近的相同数组的坐标。那么我们每次查询在[l,r]内,找出一个最大的数字且它的pre[i]<l,nxt[i]>r。我们如何用kd树解决这个问题呢?我们用三维的kd树来处理,第一维为下标i,第二维为pre[i],第三维为nxt[i],val为它本身的值。那么我们每次查询都是在一个长方体内查询最大的val就可以了。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <iostream>
  5.  
  6. using namespace std;
  7. const int maxn=1e5+;
  8. const int INF=;
  9. int a[maxn],pre[maxn],nxt[maxn],last[maxn];
  10. struct kdNode{
  11. int x[],mnn[],mxn[];
  12. int lc,rc;
  13. int val,maxv;
  14. }p[maxn],q;
  15. int n,m,cmpNo,root;
  16. int cmp(kdNode a,kdNode b){
  17. return a.x[cmpNo]<b.x[cmpNo];
  18. }
  19. void maintain(int o){
  20. int l=p[o].lc,r=p[o].rc;
  21. for(int i=;i<;i++){
  22. p[o].mnn[i]=min(min(p[l].mnn[i],p[r].mnn[i]),p[o].x[i]);
  23. p[o].mxn[i]=max(max(p[l].mxn[i],p[r].mxn[i]),p[o].x[i]);
  24. }
  25. p[o].maxv=max(max(p[l].maxv,p[r].maxv),p[o].val);
  26. }
  27. void build(int&o,int l,int r,int d){
  28. if(l>r){
  29. o=;
  30. return;
  31. }
  32. int m=l+(r-l)/;
  33. cmpNo=d,o=m;
  34. nth_element(p+l,p+m,p+r+,cmp);
  35. build(p[o].lc,l,m-,(d+)%);
  36. build(p[o].rc,m+,r,(d+)%);
  37. maintain(o);
  38. }
  39. int ans,l,r;//查询l<=x[0]<=r,x[1]<=l,x[2]>=r 空间内的最大值,这时候的kd树感觉就是高维线段树
  40. bool all(int o){
  41. if(p[o].mxn[]<=r&&p[o].mnn[]>=l&&p[o].mxn[]<l&&p[o].mnn[]>r)
  42. return true;
  43. return false;
  44. }
  45. bool have(int o){
  46. if(p[o].mnn[]<=r&&p[o].mxn[]>=l&&p[o].mnn[]<l&&p[o].mxn[]>r)
  47. return true;
  48. return false;
  49. }
  50.  
  51. void query(int o,int d){
  52. if(!o){
  53. return;
  54. }
  55. if(all(o)){
  56. ans=max(ans,p[o].maxv);
  57. return;
  58. }
  59. // ans=max(ans,p[o].val);
  60. if(p[o].x[]<=r&&p[o].x[]>=l&&p[o].x[]<l&&p[o].x[]>r)
  61. ans=max(ans,p[o].val);
  62.  
  63. int lc=p[o].lc,rc=p[o].rc;
  64. if(p[lc].maxv<p[rc].maxv){
  65. if(all(rc)){
  66. ans=max(ans,p[rc].maxv);
  67. }else if(have(rc)){
  68. query(rc,(d+)%);
  69. }
  70. if(ans<p[lc].maxv){
  71. if(all(lc))
  72. ans=max(ans,p[lc].maxv);
  73. else if(have(lc))
  74. query(lc,(d+)%);
  75. }
  76. }else{
  77. if(all(lc)){
  78. ans=max(ans,p[lc].maxv);
  79. }else if(have(lc)){
  80. query(lc,(d+)%);
  81. }
  82. if(ans<p[rc].maxv){
  83. if(all(rc))
  84. ans=max(ans,p[rc].maxv);
  85. else if(have(rc))
  86. query(rc,(d+)%);
  87. }
  88. }
  89. }
  90.  
  91. int main(){
  92. scanf("%d%d",&n,&m);
  93. for(int i=;i<=n;i++){
  94. scanf("%d",&a[i]);
  95. if(last[a[i]])
  96. pre[i]=last[a[i]];
  97. else
  98. pre[i]=;
  99. last[a[i]]=i;
  100. }
  101. memset(last,,sizeof(last));
  102. for(int i=n;i>=;i--){
  103. if(last[a[i]])
  104. nxt[i]=last[a[i]];
  105. else
  106. nxt[i]=n+;
  107. last[a[i]]=i;
  108. }
  109.  
  110. for(int i=;i<=n;i++){
  111. p[i].x[]=i;
  112. p[i].x[]=pre[i];
  113. p[i].x[]=nxt[i];
  114. p[i].val=a[i];
  115. //printf("%d %d %d\n",p[i].x[0],p[i].x[1],p[i].x[2]);
  116. }
  117. for(int i=;i<;i++){
  118. p[].mnn[i]=INF;
  119. p[].mxn[i]=-INF;
  120. }
  121.  
  122. build(root,,n,);
  123. int lastans=;
  124. for(int i=;i<=m;i++){
  125. int L,R;
  126. scanf("%d%d",&L,&R);
  127. l=min((L+lastans)%n+,(R+lastans)%n+);
  128. r=max((L+lastans)%n+,(R+lastans)%n+);
  129. // printf("%d %d\n",l,r);
  130. ans=;
  131. query(root,);
  132. printf("%d\n",ans);
  133. lastans=ans;
  134. }
  135. return ;
  136. }

【BZOJ3489】A simple rmq problem【kd树】的更多相关文章

  1. bzoj 3489: A simple rmq problem k-d树思想大暴力

    3489: A simple rmq problem Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 551  Solved: 170[Submit][ ...

  2. 【bzoj3489】 A simple rmq problem k-d树

    由于某些原因,我先打了一个错误的树套树,后来打起了$k-d$.接着因不明原因在思路上被卡了很久,在今天中午蹲坑时恍然大悟...... 对于一个数字$a_i$,我们可以用一组三维坐标$(i,pre,nx ...

  3. BZOJ3489 A simple rmq problem K-D Tree

    传送门 什么可持久化树套树才不会写呢,K-D Tree大法吼啊 对于第\(i\)个数,设其前面最后的与它值相同的位置为\(pre_i\),其后面最前的与它值相同的位置为\(aft_i\),那么对于一个 ...

  4. BZOJ3489 A simple rmq problem 【可持久化树套树】*

    BZOJ3489 A simple rmq problem Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一 ...

  5. 【题解】BZOJ3489 A Hard RMQ problem(主席树套主席树)

    [题解]A simple RMQ problem 占坑,免得咕咕咕了,争取在2h内写出代码 upd:由于博主太菜而且硬是要用指针写两个主席树,所以延后2hQAQ upd:由于博主太菜而且太懒所以他决定 ...

  6. bzoj3489 A simple rmq problem 可持久化树套树

    先预处理出两个个数组pre,next.pre[i]表示上一个与i位置数字相同的位置,若不存在则设为0:next[i]表示下一个与i位置数字相同的位置,若不存在则设为n+1.那么一个满足在区间[L,R] ...

  7. bzoj3489: A simple rmq problem (主席树)

    //========================== 蒟蒻Macaulish:http://www.cnblogs.com/Macaulish/  转载要声明! //=============== ...

  8. 【kd-tree】bzoj3489 A simple rmq problem

    Orz zyf教给蒟蒻做法 蒟蒻并不会这题正解……(可持久化树套树?...Orz 对于每个点,我们可以求出pre[i],nex[i],那么询问的答案就是:求max (a[i]),其中 i 满足(pre ...

  9. bzoj 3489 A simple rmq problem - 线段树

    Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直 ...

  10. BZOJ.3489.A simple rmq problem(主席树 Heap)

    题目链接 当时没用markdown写,可能看起来比较难受...可以复制到别的地方看比如DevC++. \(Description\) 给定一个长为n的序列,多次询问[l,r]中最大的只出现一次的数.强 ...

随机推荐

  1. 201621123006 《Java程序设计》第13周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 为了让你的系统可以被多个用户通过网 ...

  2. L198

    One of the most common birth defects throughout the world is a cleft lip. Babies born with a cleft l ...

  3. Centos 7 系统详解

      安装CentOS 7系统后,变化竟然这么大? 一.Runlevel首先一条,原来一直用的CentOS-6.5-x86_64-minimal.iso光盘镜像(400M左右无图形系统小巧便捷),而7目 ...

  4. jquery.cycle.js

    jquery.cycle.js简单用法实例 样式: a{text-decoration: none;} *{margin:0; padding:0;} /*容器设置*/ .player { width ...

  5. supervisor 使用tips

    Supervisor (http://supervisord.org) 是一个用 Python 写的进程管理工具,可以很方便的用来启动.重启.关闭进程,supervisor可以同时监控多个进程,并可以 ...

  6. Python面试题(十六)

    1.取出两个升序数组中的最小的一半的元素组成一个新的升序数组. map(lambda x, y: x if x < y else y, a, b) 答案 2.用至少2种不同的方式删除一个list ...

  7. Struts2自定义标签3模仿原有的s:if s:elseif s:else自定义自己的if elsif else

    第一步:webroot/web-inf下简历str.tld文件 <?xml version="1.0" encoding="UTF-8"?> < ...

  8. JavaWeb入门环境搭建

    一.安装配置Tomcat 1.下载 2.配置环境变量 配置JAVA_HOME环境变量,路径为JDK的根目录 3.测试Tomcat 打开浏览器,在地址栏输入http://localhost:8080可以 ...

  9. Chrome Developer Tools 中的 Preview 不显示 HTML 的问题

    Chrome Developer Tools 中的 Preview 不显示 HTML 的问题 最近升级到 Chrome V64,发现 Chrome Developer Tools 中的 Preview ...

  10. 在NOILINUX下的简易VIM配置

    位置:/etc/vim/vimrc 建议使用gedit来进行配置.即使用命令:sudo gedit /etc/vim/vimrc set mouse=a " Enable mouse usa ...