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


  题目大意 询问区间内只出现1次数的最大值。强制在线。

  考虑每位置上的数会对哪些询问作出贡献。

  显然要让位置i对答案产生贡献询问的区间需要满足 pre[i] < l <= i 并且 i <= r < suf[i] 。

  那么就可以将每个询问(l, r)看成二维平面内的一个点。

  这样的话,每个位置对答案的贡献就可以通过2维线段树来进行维护。

  为了防止MLE,所以采取标记永久化的方案。但是注意修改操作是和线段树维护的信息取max。

Code

 /**
* bzoj
* Problem#3489
* Accepted
* Time: 21836ms
* Memory: 227780k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; typedef class SegTreeNode {
public:
SegTreeNode* val;
SegTreeNode *l, *r; SegTreeNode(int val = ):val((SegTreeNode*)val) { }
SegTreeNode(int val, SegTreeNode* org):val((SegTreeNode*)val) {
l = r = org;
} int intvalue() {
return (int)val;
} SegTreeNode*& pnodeval() {
return val;
} void set(int x) {
val = (SegTreeNode*)x;
}
}SegTreeNode; #define PLimit 10000000 //int alloced = 0;
SegTreeNode pool[PLimit];
SegTreeNode null = SegTreeNode(, &null);
SegTreeNode* top = pool; SegTreeNode* newnode() {
// alloced++;
if(top >= pool + PLimit)
return new SegTreeNode(, &null);
*top = SegTreeNode(, &null);
return top++;
} typedef class SegTree {
public:
int n;
SegTreeNode* rt; SegTree() { }
SegTree(int n):n(n), rt(newnode()) { } void update2(SegTreeNode*& node, int l, int r, int ql, int qr, int val) {
if(node == &null || node == NULL)
node = newnode();
if(l == ql && r == qr) {
if(val > node->intvalue())
node->set(val);
return;
}
int mid = (l + r) >> ;
if(ql <= mid)
update2(node->l, l, mid, ql, (qr > mid) ? (mid) : (qr), val);
if(qr > mid)
update2(node->r, mid + , r, (ql > mid) ? (ql) : (mid + ), qr, val);
} void update(SegTreeNode*& node, int l, int r, int ql, int qr, int qx, int qy, int val) {
if(node == &null)
node = newnode();
if(l == ql && r == qr) {
update2(node->pnodeval(), , n, qx, qy, val);
return;
}
int mid = (l + r) >> ;
if(ql <= mid)
update(node->l, l, mid, ql, (qr > mid) ? (mid) : (qr), qx, qy, val);
if(qr > mid)
update(node->r, mid + , r, (ql > mid) ? (ql) : (mid + ), qr, qx, qy, val);
} int query2(SegTreeNode*& node, int l, int r, int idx) {
if(node == NULL || node == &null)
return ;
if(l == idx && r == idx)
return node->intvalue();
int mid = (l + r) >> , rt = node->intvalue(), cmp = ;
if(idx <= mid)
cmp = query2(node->l, l, mid, idx);
else
cmp = query2(node->r, mid + , r, idx);
return (cmp > rt) ? (cmp) : (rt);
} int query(SegTreeNode*& node, int l, int r, int idx, int bidx) {
if(node == &null)
return ;
if(l == idx && r == idx)
return query2(node->pnodeval(), , n, bidx);
int mid = (l + r) >> , rt = query2(node->pnodeval(), , n, bidx), cmp;
if(idx <= mid)
cmp = query(node->l, l, mid, idx, bidx);
else
cmp = query(node->r, mid + , r, idx, bidx);
return (cmp > rt) ? (cmp) : (rt);
}
}SegTree; int n, m;
int *ar;
int *pre, *suf;
int *head;
SegTree st; inline void init() {
scanf("%d%d", &n, &m);
st = SegTree(n);
ar = new int[(n + )];
pre = new int[(n + )];
suf = new int[(n + )];
head = new int[(n + )];
for(int i = ; i <= n; i++)
scanf("%d", ar + i);
} inline void solve() {
memset(head, , sizeof(int) * (n + ));
for(int i = ; i <= n; i++)
pre[i] = head[ar[i]], head[ar[i]] = i;
fill(head, head + n + , n + );
for(int i = n; i; i--)
suf[i] = head[ar[i]], head[ar[i]] = i; for(int i = ; i <= n; i++)
st.update(st.rt, , n, pre[i] + , i, i, suf[i] - , ar[i]);//, fprintf(stderr, "%d: Memory Usage: %d (%d nodes)\n", i, alloced * sizeof(SegTreeNode), alloced);
int lastans = , x, y;
while(m--) {
scanf("%d%d", &x, &y);
x = (x + lastans) % n + ;
y = (y + lastans) % n + ;
if(x > y) swap(x, y);
lastans = st.query(st.rt, , n, x, y);
printf("%d\n", lastans);
}
} int main() {
init();
solve();
return ;
}

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——主席树套线段树

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

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

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

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

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

  5. BZOJ 3489: A simple rmq problem

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

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

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

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

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

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

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

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

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

随机推荐

  1. 实现多线程异步自动上传本地文件到 Amazon S3

    最近抽空做个小工具,使用AWSSDK 对本地文件目录监控,并自动同步上传文件到S3 的过程,使用的是多线程异步上传,针对大文件进行了分块 参考文献: https://www.codeproject.c ...

  2. php 提取多维数组指定列

    前言:有时候在开发中会遇到这样的问题,我们需要把有规律的多维数组按照纵向(列)取出,有下面的方法可用: 我们将拿下面的数组来处理: 1 $arr = array( 2 '0' => array( ...

  3. sqli-labs(六)

    第十一关: 这关是一个登陆口,也是一个sql注入的漏洞,也就是常说的万能密码. 在输入框账号密码种分别输入 1'  和1'  页面会报错. 后台使用的单引符号进行的拼接.账号输入1' or '1'=' ...

  4. 001-http协议-请求报文以及服务器响应状态

    Http协议的几个概念: 1.连接(Connection):浏览器和服务器之间传输数据的通道. 一般请求完毕就关闭,http不保持连接.不保持连接会降低处理速度(因为建立连接速度很慢),保持连接的话就 ...

  5. ip and port check 正则

    在网页开发中可能会遇到需要对在页面输入的ip和端口进行正确性验证,那么正则表达式就是最有力的工具: 1:ip的正则表达式: 格式是由“.”分割的四部分,每部分的范围是0-255: 每段的正则可以分几部 ...

  6. Comparator与Comparable用法与区别

    一.概述.   Comparator和Comparable两者都属于集合框架的一部分,都是用来在对象之间进行比较的,但两者又有些许的不同,我们先通过一个例子来看一下他们的区别,然后再分别学习下它们的源 ...

  7. 04-树6 Complete Binary Search Tree(30 分)

    title: 04-树6 Complete Binary Search Tree(30 分) date: 2017-11-12 14:20:46 tags: - 完全二叉树 - 二叉搜索树 categ ...

  8. Problem(莫比乌斯反演)

    我不是传送门 题意 : 中文题目不解释 求gcd(x,y) = k (a<=x<=b, c<=y<=d); 根据gcd(ka,kb) = k*gcd(a,b), 可将问题转化为 ...

  9. 【2017-03-20】HTML框架,标题栏插入小图标,锚点,插入音频视频,滚动效果

    一.html框架   iframe 在网页中嵌入一个别的网页 1.格式: <iframe  src="链接地址" width="" height=&quo ...

  10. ubuntu16.04——WingIDE安装 操作服务器是一件很好玩的事情

    1.在服务器上部署环境时,区分linux 系统和winddos系统 2.下载安装包: 3.输入命令操作 4.进入相对应的目录下: 5.命令 6.发生错误,更新环境 7.安装成功