Description

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

Input

第一行为两个整数N,M。M是询问数,N是序列的长度(N<=100000,M<=200000)

第二行为N个整数,描述这个序列{ai},其中所有1<=ai<=N

再下面M行,每行两个整数x,y,

询问区间[l,r]由下列规则产生(OIER都知道是怎样的吧>_<):

l=min((x+lastans)mod n+1,(y+lastans)mod n+1);

r=max((x+lastans)mod n+1,(y+lastans)mod n+1);

Lastans表示上一个询问的答案,一开始lastans为0

Output

一共M行,每行给出每个询问的答案。

题解: 对于一个区间 $[l,r]$ 一个数只出现依次说明上次出现在 $[1,l-1]$ 中(或没出现),下一次出现在 $[r+1,n]$ 中(或没出现).
直接维护一个 3 维 $KDtree$ 即可.
第一维维护 $pre_{i}$,第二位维护 $i$ 本身,第三维维护下一次出现的位置.
每次按照上述条件直接进行数点即可.
思路还是非常巧妙的.

#include<bits/stdc++.h>
#define maxn 200000
#define inf 100000000
#define mid ((l+r)>>1)
#define lson (t[x].ch[0])
#define rson (t[x].ch[1])
using namespace std;
void setIO(string s)
{
string in=s+".in";
freopen(in.c_str(),"r",stdin);
}
int n,Q,lastans,d,_ans;
int lst[maxn],nex[maxn],pos[maxn],arr[maxn];
struct Node
{
int ch[2],minv[3],maxv[3],p[3],w,_max;
}t[maxn];
bool cmp(Node a,Node b)
{
if(a.p[d]==b.p[d] && a.p[(d+1)%3]==b.p[(d+1)%3]) return a.p[(d+2)%3] < b.p[(d+2)%3];
if(a.p[d]==b.p[d]) return a.p[(d+1)%3] < b.p[(d+1)%3];
return a.p[d] < b.p[d];
}
void pushup(int x,int y)
{
for(int i=0;i<3;++i)
{
t[x].minv[i]=min(t[x].minv[i],t[y].minv[i]);
t[x].maxv[i]=max(t[x].maxv[i],t[y].maxv[i]);
}
t[x]._max=max(t[x]._max,t[y]._max);
}
int build(int l,int r,int o)
{
d=o;
nth_element(t+l,t+mid,t+1+r,cmp);
for(int i=0;i<3;++i) t[mid].minv[i]=t[mid].maxv[i]=t[mid].p[i];
t[mid].ch[0]=t[mid].ch[1]=0;
t[mid]._max=t[mid].w;
if(mid>l)
{
t[mid].ch[0]=build(l,mid-1,(o+1)%3);
pushup(mid,t[mid].ch[0]);
}
if(r>mid)
{
t[mid].ch[1]=build(mid+1,r,(o+1)%3);
pushup(mid,t[mid].ch[1]);
}
return mid;
}
int isout(int x,int l,int r)
{
if(t[x].minv[0] >= l || t[x].maxv[2] <= r || t[x].minv[1] > r || t[x].maxv[1] < l) return 1;
return 0;
}
int isin(int x,int l,int r)
{
if(t[x].maxv[0] < l && t[x].minv[2] > r && t[x].minv[1] >= l && t[x].maxv[1] <= r) return 1;
return 0;
}
void query(int x,int l,int r)
{
if(isout(x, l, r)) return;
if(isin(x, l, r))
{
_ans=max(_ans, t[x]._max);
return;
}
if(t[x].p[0] < l && t[x].p[1] >= l && t[x].p[1] <= r && t[x].p[2] > r) _ans=max(_ans, t[x].w);
if(lson && t[lson]._max > _ans) query(lson, l, r);
if(rson && t[rson]._max > _ans) query(rson, l, r);
}
int main()
{
int i,j,x,y,root,a;
// setIO("input");
scanf("%d%d",&n,&Q);
for(i=1;i<=n;++i)
{
scanf("%d",&a);
nex[pos[a]]=i, lst[i]=pos[a], pos[a]=i, arr[i]=a;
}
for(i=1;i<=n;++i)
{
t[i].p[0]=lst[i], t[i].p[1]=i, t[i].p[2] = nex[i] ? nex[i] : n + 1, t[i].w=arr[i];
}
root=build(1,n,0);
while(Q--)
{
scanf("%d%d",&x,&y);
x=(x+lastans) % n + 1;
y=(y+lastans) % n + 1;
if(x > y) swap(x, y);
_ans = -inf;
query(root, x, y);
lastans = (_ans == -inf ? 0 : _ans);
printf("%d\n",lastans);
}
return 0;
}

  

BZOJ 3489: A simple rmq problem KDtree的更多相关文章

  1. BZOJ 3489 A simple rmq problem ——KD-Tree

    考前写写板子. 用$(i,pre[i],nxt[i])$来描述一个点,然后就变成了区间求最值的问题. KD-Tree 由低维转向高维的方法,可以用来敲暴力. 剩下就是KD-Tree的基本操作了. #i ...

  2. BZOJ 3489: A simple rmq problem (KD-tree做法)

    KD树水过这道可持久化树套树-其实就是个三维偏序 题解戳这里 CODE #include <bits/stdc++.h> using namespace std; #define ls ( ...

  3. BZOJ 3489: A simple rmq problem

    3489: A simple rmq problem Time Limit: 40 Sec  Memory Limit: 600 MBSubmit: 1594  Solved: 520[Submit] ...

  4. 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][ ...

  5. [BZOJ 3489] A simple rmq problem 【可持久化树套树】

    题目链接:BZOJ - 3489 题目分析 “因为是OJ上的题,就简单点好了.”——出题人 真的..好..简单... 首先,我们求出每个数的前一个与它相同的数的位置,即 prev[i] ,如果前面没有 ...

  6. BZOJ 3489 A simple rmq problem 可持久化KDtree/二维线段树

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3489 题意概述: 给出一个序列,每次询问一个序列区间中仅出现了一次的数字最大是多少,如果 ...

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

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

  8. bzoj 3489 A simple rmq problem——主席树套线段树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3489 题解:http://www.itdaan.com/blog/2017/11/24/9b ...

  9. BZOJ 3489 A simple rmq problem(可持久化线段树)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3489 题意:一个数列.每次询问一个区间内出现一次的最大的数字是多少. 思路:设la ...

随机推荐

  1. http://www.html5tricks.com/demo/jiaoben2255/index.html 排序算法jquery演示源代码

      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.or ...

  2. Android中apk动态载入技术研究(2)android插件化及实现

    了解了android中类载入的前期知识点后,来看看android中DexClassLoader详细的实现     详细载入流程例如以下:     宿主程序会到文件系统比方SD卡中去载入APK[1],然 ...

  3. js滚轮换切屏

    因为全项目不是自己写的,仅仅是帮别人写js滚轮代码,并且别人项目也还未上线.所以仅仅贴出自己写的那段部分代码, 效果:鼠标滚轮滚动时.网頁屏幕一屏一屏的上下切换 (下面代码在本地电脑的IE,chrom ...

  4. Erlang下与其他程序和语言的通信机制(2)

    前面聊了普通端口,今天聊下链入式驱动端口,以及NIFs. 链入式驱动端口 如上图所示,链入式驱动端口与Erlang虚拟机存在于同一个OS进程中. 在Erlang这边与普通端口类似,所有与链入式驱动端口 ...

  5. 更改App.config里的值并保存

    using System; using System.Collections.Generic; using System.Configuration; using System.IO; using S ...

  6. https://github.com/Boris-Em/BEMCheckBox

    https://github.com/Boris-Em/BEMCheckBox BEMCheckBox BEMCheckBox is an open source library making it ...

  7. IOS系统控件高度

    以下是常见的几种控件的高度.Statusbar,Navigationbar和Tabbar的宽度极其图标大小. 下表是更为详细的参数,包括了Statusbar,Navigationbar.Tabbar. ...

  8. XAML实例教程系列 - 开篇(一)

    XAML实例教程系列 - 开篇 2012-05-14 11:47 by jv9, 5588 阅读, 8 评论, 收藏, 编辑 去年,曾答应银光中国论坛的朋友推出一个关于XAML语言实例教程系列,帮助学 ...

  9. [Codeforces Round495A] Sonya and Hotels

    [题目链接] https://codeforces.com/contest/1004/problem/A [算法] 直接按题意模拟即可 时间复杂度 :O(NlogN) [代码] #include< ...

  10. algorithm库———count&&countif

    algorithm头文件定义了一个count的函数,其功能类似于find.这个函数使用一对迭代器和一个值做参数,返回这个值出现次数的统计结果. 编写程序读取一系列int型数据,并将它们存储到vecto ...