A simple rmq problem

题目大意:给定一个长度为$n$的序列,给出$m$个询问:在$[l,r]$之间找到一个在这个区间里只出现过一次的最大的数。

注释:$1\le n\le 10^5$,$1\le mle 2\cdot 10^5$。


想法

我的第一想法是莫队。

结果发现是强制在线(离线我也不会...

想了想其实$KD-Tree$还是比较显然的。

我们设$l_i$表示$a_i$上一次出现的位置,$r_i$表示下一次。

紧接着我们把第$i$个数转化为三维坐标轴上的点$(l_i,i,r_i)$。

用$KD-Tree$维护直接查即可。

Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
int v[N],lst[N],dic[N],nxt[N],d,l,r,ans,rt;
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {int x=0,f=1; char c=nc(); while(c<48) {if(c=='-') f=-1; c=nc();} while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x*f;}
inline void Max(int &x,int y) {x=x>y?x:y;}
inline void Min(int &x,int y) {x=x<y?x:y;}
struct Node {int p[3],mx[3],mn[3],ans,size,val,ls,rs;}a[N];
inline bool cmp(const Node &a,const Node &b)
{
for(int i=0;i<3;i++) if(a.p[(d+i)%3]!=b.p[(d+i)%3]) return a.p[(d+i)%3]<b.p[(d+i)%3];
return true;
}
inline void pushup(int x,int k)
{
a[x].size+=a[k].size;
for(int i=0;i<3;i++) Max(a[x].mx[i],a[k].mx[i]),Min(a[x].mn[i],a[k].mn[i]);
Max(a[x].ans,a[k].ans);
}
int build(int l,int r,int now)
{
int mid=(l+r)>>1;
d=now; nth_element(a+l,a+mid,a+r+1,cmp);
for(int i=0;i<3;i++) a[mid].mx[i]=a[mid].mn[i]=a[mid].p[i];
a[mid].ans=a[mid].val;
if(l<mid) a[mid].ls=build(l,mid-1,(now+1)%3),pushup(mid,a[mid].ls);
if(mid<r) a[mid].rs=build(mid+1,r,(now+1)%3),pushup(mid,a[mid].rs);
return mid;
}
bool judge(int x)
{
return a[x].ans>ans&&a[x].mx[0]>=l&&a[x].mn[0]<=r&&a[x].mn[1]<l&&a[x].mx[2]>r;
}
void query(int x)
{
if(!x||!judge(x)) return;
if(a[x].p[0]>=l&&a[x].p[0]<=r&&a[x].p[1]<l&&a[x].p[2]>r) Max(ans,a[x].val);
query(a[x].ls); query(a[x].rs);
}
int main()
{
int n=rd(),m=rd();
for(int i=1;i<=n;i++) v[i]=rd(),lst[i]=dic[v[i]],nxt[dic[v[i]]]=i,dic[v[i]]=i;
for(int i=1;i<=n;i++) a[i].p[0]=i,a[i].p[1]=lst[i],a[i].p[2]=nxt[i]?nxt[i]:n+1,a[i].val=v[i];
rt=build(1,n,0); while(m--)
{
l=(rd()+ans)%n+1,r=(rd()+ans)%n+1; if(l>r) swap(l,r);
ans=0,query(rt); printf("%d\n",ans);
}
return 0;
}

小结:$KD-Tree$虽然是一个暴力,但是它的思想还是非常不错的。

最新文章

  1. TaintDroid深入剖析之启动篇
  2. 移动端全兼容的flexbox速成班
  3. 用C#Winform写个简单的批量清空文件内容和删除文件的小工具
  4. .Net core Linux环境安装
  5. thinking in java之Collections工具类的使用
  6. LK 光流法简介
  7. 266. Palindrome Permutation
  8. [转]Oracle快速入门
  9. seajs第二节,seajs各模块依赖关系
  10. oracle 绿色版本 instantclient 使用说明
  11. 与众不同 windows phone (23) - Device(设备)之硬件状态, 系统状态, 网络状态
  12. VC生成的DLL给QT的EXE调用时lib路径问题小结
  13. springmvc集成aop记录操作日志
  14. 如何卸载CentOS自带的apache
  15. 201521123052《Java程序设计》第10周学习总结
  16. HttpServletRequest对象
  17. iOS中 CoreGraphics快速绘图(详解) 韩俊强的博客
  18. 别人的Linux私房菜(5)首次CentOS7与帮助等
  19. linux之基本命令进阶
  20. 在linux下用命令行编译 java的eclipse项目

热门文章

  1. SpringMVC的简单传值
  2. 网络基础编程_5.4聊天室-IOCP服务器
  3. Python+Selenium 自动化测试获取测试报告内容并发送邮件
  4. 解决android的键盘弹出时,html页面的高度被压缩
  5. CAD参数绘制批注(com接口)
  6. spring cloud Bug之was unable to refresh its cache! status = Cannot execute request on any known server
  7. 笔试算法题(12):整数的string到int转换 &amp; 两个栈实现队列
  8. idea cannot download sources解决办法
  9. C++动态申请内存 new T()与new T[]的区别
  10. sort cmp函数的写法 (特判排序 二级排序)