BZOJ 3489: A simple rmq problem
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
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
10
10
0
0
10
0
4
0
4
HINT
注意出题人为了方便,input的第二行最后多了个空格。
2015.6.24新加数据一组,2016.7.9放至40S,600M,但未重测
Source
参考了网上的一些做法,可持久化树套树什么的实在吃不消,于是采用了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的更多相关文章
- 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][ ...
- [BZOJ 3489] A simple rmq problem 【可持久化树套树】
题目链接:BZOJ - 3489 题目分析 “因为是OJ上的题,就简单点好了.”——出题人 真的..好..简单... 首先,我们求出每个数的前一个与它相同的数的位置,即 prev[i] ,如果前面没有 ...
- bzoj 3489 A simple rmq problem - 线段树
Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直 ...
- BZOJ 3489 A simple rmq problem(可持久化线段树)
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3489 题意:一个数列.每次询问一个区间内出现一次的最大的数字是多少. 思路:设la ...
- BZOJ 3489 A simple rmq problem 可持久化KDtree/二维线段树
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3489 题意概述: 给出一个序列,每次询问一个序列区间中仅出现了一次的数字最大是多少,如果 ...
- bzoj 3489 A simple rmq problem——主席树套线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3489 题解:http://www.itdaan.com/blog/2017/11/24/9b ...
- bzoj 3489 A simple rmq problem —— 主席树套线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3489 题解:http://www.itdaan.com/blog/2017/11/24/9b ...
- BZOJ.3489.A simple rmq problem(主席树 Heap)
题目链接 当时没用markdown写,可能看起来比较难受...可以复制到别的地方看比如DevC++. \(Description\) 给定一个长为n的序列,多次询问[l,r]中最大的只出现一次的数.强 ...
- BZOJ 3489: A simple rmq problem(K-D Tree)
Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 2579 Solved: 888[Submit][Status][Discuss] Descripti ...
随机推荐
- 流程控制和循环.png
- VMware安装CentOS时,无法以图形界面安装解决办法
有的同学问: 用虚拟机软件(vmware.VirtualBox)安装CentOS系统时, 安装过程中没有中文,也没有出现图形界面,都是以命令行方式去安装, 有时候又会出现图形界面,不知道哪里配置的问题 ...
- cmd命令汇总
一 cmd 命令 cmd命令大全(第一部分) winver---------检查Windows版本 wmimgmt.msc----打开windows管理体系结构(WMI) wupdmgr------ ...
- 【原】Bootstrap+Knockout.JS+ASP.Net MVC3+PetaPOCO实现CRUD操作
1.需求: 1.1)页面要美观大气 1.2)前端代码要简洁清晰,要用MVC或是MVVM框架 1.3)服务端要用MVC框架,要Rest风格 1.4)数据访问要用ORM 2.效果: 2.1)列表 2.2) ...
- 3.3 js函数
1.函数语法: 函数声明的方式:function 函数名(参数1,参数2-){//函数体;}函数调用:函数名(参数1,参数2-); 函数内不一定都指定返回值. 如果需要指定返回值,可用 return ...
- ABAP关键字SUBMIT的简单例子和学习小记
网上有关SUBMIT实现程序调用的例子稍显复杂,而相关的参考和解释则不是很完善.本文给出一个SUBMIT的小示例程序(代码见文末),实现了最简单的程序间调用及返回值,以及SAP官方文档中相关内容的翻译 ...
- VisualStudio 调试Linux
微软自从换了CEO之后,拥抱开源的步伐真实越来越快了,这部,现在VS可以跟踪Linux程序了 http://blogs.msdn.com/b/vcblog/archive/2015/11/18/ann ...
- 谨慎使用Sql server data tool 架构比对排除
现象:某个架构始终不能更新 VS中使用SSDT很方便,进行架构比对时,可以选择性的更新.但在排除操作上,要相当谨慎.往往排除的并不是一个差异项. 如下图,表或视图的差异,如果有多处,可以选 ...
- GreenPlum高效去除表重复数据
1.针对PostgreSQL数据库表的去重复方法基本有三种,这是在网上查找的方法,在附录1给出.但是这些方法对GreenPlum来说都不管用. 2.数据表分布在不同的节点上,每个节点的ctid是唯一的 ...
- 在tmux中的vi 上下左右键变为了ABCD等字符
在本机上用vim编辑时,上下左右键没有问题,但是在tmux中确出现ABCD等字符. 原因是在tmux这个终端,默认做了字符转换,网上搜了很多答案,解决问题的设置是: set term=xterm