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. Hibernate插入错误:GenericJDBCException: could not insert:

    数据库中一般不能建立user(表名为User)表,将User类改名,又一次建立映射,问题就能够解决 当然,还有还有一种情况.就是类中id类型错误.要设置为Integer型才干够设置自己主动增长,否则也 ...

  2. 【剑指offer】斐波那契序列与跳台阶

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/25337983 剑指offer上的第9题,简单题,在九度OJ上測试通过. 主要注意下面几点: ...

  3. Ubuntu下用命令行快速打开各类型文件(转)

    nautilus /media/pm/文档/book/system/必读nautilus /media/pm/文档/book/android/ndk 内核/framerwork/android wai ...

  4. 【SQL Server】SQL触发器经验详解

    [SQL Server]SQL触发器经验详解 | 浏览: 4314 | 更新: 2013-01-07 15:33 25 11 全文阅读分步阅读   加入杂志 步骤 1 2 3 4 5 6 7 8   ...

  5. POJ 3268 最短路应用

    POJ3268 题意很简单 正向图跑一遍SPFA 反向图再跑一边SPFA 找最大值即可. #include<iostream> #include<cstdio> #includ ...

  6. bzoj1833

    http://www.lydsy.com/JudgeOnline/problem.php?id=1833 2.5个小时就花在这上面了... 水到200题了...然并卵,天天做水题有什么前途... #i ...

  7. openstack instance resize to

    Icehouse resize No valid host was found Hi all!! We're currently experimenting an error that's it's ...

  8. Spark SQL中 RDD 转换到 DataFrame (方法二)

    强调它与方法一的区别:当DataFrame的数据结构不能够被提前定义.例如:(1)记录结构已经被编码成字符串 (2) 结构在文本文件中,可能需要为不同场景分别设计属性等以上情况出现适用于以下方法.1. ...

  9. E20171015-hm

    quirk   n. 怪癖; 奇事,巧合; 突然的弯曲; propagation  n. 宣传; 传播,传输,蔓延,扩展,波及深度; [生]繁殖法,[地]传导; 培养; immediate  adj. ...

  10. 34、JavaScript面向对象(内置构造函数&相关方法|属性|运算符&继承&面向对象)

    一.面向对象 1.1 this的指向问题 要看清楚最终的函数调用者是谁. IIFE也被当做函数直接运行,IIFE的this都是window对象 函数的arguments是类数组对象,比如传入的第0项参 ...