3489: A simple rmq problem

Time Limit: 40 Sec  Memory Limit: 600 MB
Submit: 1594  Solved: 520
[Submit][Status][Discuss]

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行,每行给出每个询问的答案。

Sample Input

10 10
6 4 9 10 9 10 9 4 10 4
3 8
10 1
3 4
9 4
8 1
7 8
2 9
1 1
7 3
9 9

Sample Output

4
10
10
0
0
10
0
4
0
4

HINT

注意出题人为了方便,input的第二行最后多了个空格。

2015.6.24新加数据一组,2016.7.9放至40S,600M,但未重测

Source

[Submit][Status][Discuss]

参考了网上的一些做法,可持久化树套树什么的实在吃不消,于是采用了KD-Tree的方法。

考虑一个点,在哪个区间内它是唯一出现的呢?

设prev[i]为上一个和i处权值相同的位置,next[i]为下一个和i处权值相同的位置,显然在(prev[i],next[i])这个区间内,i点是该权值唯一出现的位置。

对于一个询问(ql,qr),我们可以转换为:找出满足 prev[i] < ql 且 next[i] > qr 且 ql <= i <= qr 的i中,权值最大的i。这个就是KD-Tree维护三维的区间最值问题。

 #include <bits/stdc++.h>

 inline int getC(void) {
static const int siz = ; static char buf[siz];
static char *hd = buf + siz;
static char *tl = buf + siz; if (hd == tl)
fread(hd = buf, , siz, stdin); return int(*hd++);
} inline int getI(void) {
register int ret = ;
register int neg = false;
register int bit = getC(); for (; bit < ; bit = getC())
if (bit == '-')neg ^= true; for (; bit > ; bit = getC())
ret = ret * + bit - ''; return neg ? -ret : ret;
} template <class T>
inline T min(const T &a, const T &b) {
return a < b ? a : b;
} template <class T>
inline T max(const T &a, const T &b) {
return a > b ? a : b;
} const int maxn = ; int n, m;
int answer;
int num[maxn]; int next[maxn];
int prev[maxn];
int last[maxn]; int value[maxn][]; int pos[maxn];
int maxv[maxn];
int lson[maxn];
int rson[maxn];
int mini[maxn][];
int maxi[maxn][]; int qryL, qryR; int cmpK; inline bool cmp(const int &a, const int &b) {
return value[a][cmpK] < value[b][cmpK];
} int build(int l, int r, int k) {
int mid = (l + r) >> ; cmpK = k;
std::nth_element(
pos + l, pos + mid, pos + r + , cmp);
maxv[mid] = num[pos[mid]];
for (int i = ; i < ; ++i)
mini[mid][i] = maxi[mid][i] = value[pos[mid]][i];
if (l < mid) {
lson[mid] = build(l, mid - , (k + ) % );
maxv[mid] = max(maxv[mid], maxv[lson[mid]]);
for (int i = ; i < ; ++i) {
mini[mid][i] = min(mini[mid][i], mini[lson[mid]][i]);
maxi[mid][i] = max(maxi[mid][i], maxi[lson[mid]][i]);
}
}
if (r > mid) {
rson[mid] = build(mid + , r, (k + ) % );
maxv[mid] = max(maxv[mid], maxv[rson[mid]]);
for (int i = ; i < ; ++i) {
mini[mid][i] = min(mini[mid][i], mini[rson[mid]][i]);
maxi[mid][i] = max(maxi[mid][i], maxi[rson[mid]][i]);
}
}
return mid;
} inline bool check(int t) {
if (mini[t][] > qryR || maxi[t][] < qryL)return false;
if (mini[t][] >= qryL || maxi[t][] <= qryR)return false;
return true;
} void query(int t) {
if (mini[t][] >= qryL && maxi[t][] <= qryR && maxi[t][] < qryL && mini[t][] > qryR)
{ answer = max(answer, maxv[t]); return; }
if (pos[t] >= qryL && pos[t] <= qryR && prev[pos[t]] < qryL && next[pos[t]] > qryR)
answer = max(answer, num[pos[t]]);
if (maxv[lson[t]] > maxv[rson[t]]) {
if (lson[t] && maxv[lson[t]] > answer && check(lson[t]))query(lson[t]);
if (rson[t] && maxv[rson[t]] > answer && check(rson[t]))query(rson[t]);
}
else {
if (rson[t] && maxv[rson[t]] > answer && check(rson[t]))query(rson[t]);
if (lson[t] && maxv[lson[t]] > answer && check(lson[t]))query(lson[t]);
}
} signed main(void) {
n = getI();
m = getI(); for (int i = ; i <= n; ++i)
num[i] = getI(); for (int i = ; i <= n; ++i)
last[i] = ; for (int i = ; i <= n; ++i)
prev[i] = last[num[i]], last[num[i]] = i; for (int i = n; i >= ; --i)
last[i] = n + ; for (int i = n; i >= ; --i)
next[i] = last[num[i]], last[num[i]] = i; for (int i = ; i <= n; ++i) {
pos[i] = i;
value[i][] = i;
value[i][] = prev[i];
value[i][] = next[i];
} int root = build(, n, ); for (int i = ; i <= m; ++i) {
int x = getI();
int y = getI();
qryL = (x + answer) % n + ;
qryR = (y + answer) % n + ;
if (qryL > qryR)
qryL ^= (qryR ^= (qryL ^= qryR));
answer = ; query(root); printf("%d\n", answer);
}
}

@Author: YouSiki

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

  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. [BZOJ 3489] A simple rmq problem 【可持久化树套树】

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. BZOJ 3489: A simple rmq problem(K-D Tree)

    Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 2579  Solved: 888[Submit][Status][Discuss] Descripti ...

随机推荐

  1. 【问题】关于Mapper not initialized的问题

    ERROR -- ::, [ ] nHandling.AbpApiExceptionFilterAttribute - Mapper not initialized. Call Initialize ...

  2. linux(八)__yum工具

    自动处理依赖性关系,并且一次安装所有依赖的软体包,无须繁琐地一次次下载.安装. 什么是yum? yum工具实例: 因为yum指定的软件仓库源是国外的网站,在国内访问较慢.我们更改它的仓库源. 首先先备 ...

  3. sea.js模块化编程

    * 为什么要模块化? 解决文件依赖 解决命名冲突 ; var var2 = 2; function fn1(){ } function fn2(){ } return { fn1: fn1, fn2: ...

  4. HTML5 Canvas玩转酷炫大波浪进度图

    如上图所见,本文就是要实现上面那种效果. 由于最近AlloyTouch要写一个下拉刷新的酷炫loading效果.所以首选大波浪进度图. 首先要封装一下大波浪图片进度组件.基本的原理是利用Canvas绘 ...

  5. Vector Tile

    Mapbox Vector Tile Specification A specification for encoding tiled vector data. <?XML:NAMESPACE ...

  6. 利用私有的API获得手机上所安装的所有应用信息(包括版本,名称,bundleID,类型)

    MobileCoreService这个系统的库,里面有个私有的类LSApplicationWorkspace ,利用运行时可以获得私有类里面的方法,- (id)allInstalledApplicat ...

  7. 了解JavaScript 对象属性的标签

    对象属性的标签 value(属性值), writable(属性可写), enumerable(属性可枚举), configurable(属性可配置), 这些属性标签使对象所持有的属性体现出不同的特性, ...

  8. AngularJS 系列 01 - HelloWorld和数据绑定

    目录导读: AngularJS 系列 学习笔记 目录篇 前言: 好记性不如烂键盘,随笔就是随手笔记,希望以后有用. 本篇目录: 1. Hello World 2. AngularJS中的数据绑定 3. ...

  9. 数据库设计范式2——BC范式和第四范式

    我在很久之前的一篇文章中介绍了数据库模型设计中的基本三范式,今天,我来说一说更高级的BC范式和第四范式. 回顾 我用大白话来回顾一下什么是三范式: 第一范式:每个表应该有唯一标识每一行的主键. 第二范 ...

  10. [MySQL性能优化系列]提高缓存命中率

    1. 背景 通常情况下,能用一条sql语句完成的查询,我们尽量不用多次查询完成.因为,查询次数越多,通信开销越大.但是,分多次查询,有可能提高缓存命中率.到底使用一个复合查询还是多个独立查询,需要根据 ...