KD树水过这道可持久化树套树…其实就是个三维偏序 题解戳这里

CODE

#include <bits/stdc++.h>
using namespace std;
#define ls (t[o].ch[0])
#define rs (t[o].ch[1])
const int MAXN = 100005;
const int inf = 1e9;
inline void read(int &num) {
char ch; int flg=1;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')flg=-flg;
for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
num*=flg;
}
int D, rt;
struct Node {
int d[3], v;
inline bool operator <(const Node &o)const {
return d[D] < o.d[D];
}
}arr[MAXN];
struct KD_node {
int ch[2], mn[3], mx[3], val;
Node a;
inline void clear() {
ch[0]=ch[1]=val=a.v=0;
for(int l = 0; l < 3; ++l)
mn[l]=mx[l]=a.d[l]=0;
}
}t[MAXN];
struct Query {
int mn[3], mx[3];
};
int bin[MAXN], top, tot, cur;
inline int NewNode() {
if(!top) return ++tot;
t[bin[top]].clear();
return bin[top--];
}
inline void chkmin(int &x, int y) { if(y < x) x = y; }
inline void chkmax(int &x, int y) { if(y > x) x = y; }
inline void mt(int x, int y) {
for(int l = 0; l < 3; ++l)
chkmin(t[x].mn[l], t[y].mn[l]),
chkmax(t[x].mx[l], t[y].mx[l]);
chkmax(t[x].val, t[y].val);
}
inline void upd(int o) {
for(int l = 0; l < 3; ++l)
t[o].mn[l] = t[o].mx[l] = t[o].a.d[l];
t[o].val = t[o].a.v;
if(ls) mt(o, ls);
if(rs) mt(o, rs);
}
inline int build(int l, int r, int nd) {
int mid = (l + r) >> 1; D = nd;
nth_element(arr+l, arr+mid, arr+r+1);
int o = NewNode(); t[o].a = arr[mid];
if(l < mid) ls = build(l, mid-1, (nd+1)%3); else ls = 0;
if(r > mid) rs = build(mid+1, r, (nd+1)%3); else rs = 0;
upd(o); return o;
}
inline int judge(int o, Query q) {
if(q.mn[0] <= t[o].mn[0] && t[o].mx[0] <= q.mx[0]
&& q.mn[1] <= t[o].mn[1] && t[o].mx[1] <= q.mx[1]
&& q.mn[2] <= t[o].mn[2] && t[o].mx[2] <= q.mx[2]) return 1;
if(q.mn[0] > t[o].mx[0] || q.mx[0] < t[o].mn[0]
|| q.mn[1] > t[o].mx[1] || q.mx[1] < t[o].mn[1]
|| q.mn[2] > t[o].mx[2] || q.mx[2] < t[o].mn[2]) return -1;
return 0;
}
int lastans;
inline void query(int o, Query q) {
if(!o || t[o].val <= lastans) return;
int tmp = judge(o, q);
if(tmp == 1) chkmax(lastans, t[o].val);
else if(tmp == -1) return;
else {
if(q.mn[0] <= t[o].a.d[0] && t[o].a.d[0] <= q.mx[0]
&& q.mn[1] <= t[o].a.d[1] && t[o].a.d[1] <= q.mx[1]
&& q.mn[2] <= t[o].a.d[2] && t[o].a.d[2] <= q.mx[2])
chkmax(lastans, t[o].a.v);
int which = t[ls].val < t[rs].val;
query(t[o].ch[which], q);
query(t[o].ch[which^1], q);
}
}
int n, m;
int num[MAXN], pre[MAXN], suf[MAXN], lst[MAXN];
int main () {
read(n), read(m);
for(int i = 1; i <= n; ++i) lst[i] = 0, read(num[i]);
for(int i = 1; i <= n; ++i) pre[i] = lst[num[i]], lst[num[i]] = i;
for(int i = 1; i <= n; ++i) lst[i] = n+1;
for(int i = n; i >= 1; --i) suf[i] = lst[num[i]], lst[num[i]] = i;
for(int i = 1; i <= n; ++i) arr[i] = (Node){{i, pre[i], suf[i]}, num[i]};
rt=build(1, n, 0);
int x, y;
for(int i = 1; i <= m; ++i) {
read(x), read(y);
x = (lastans + x) % n + 1,
y = (lastans + y) % n + 1;
if(y < x) swap(x, y);
lastans = 0;
query(rt, (Query){{x, 0, y+1}, {y, x-1, n+1}});
printf("%d\n", lastans);
}
}

BZOJ 3489: A simple rmq problem (KD-tree做法)的更多相关文章

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

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

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

  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 【可持久化树套树】

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

  5. BZOJ3489 A simple rmq problem K-D Tree

    传送门 什么可持久化树套树才不会写呢,K-D Tree大法吼啊 对于第\(i\)个数,设其前面最后的与它值相同的位置为\(pre_i\),其后面最前的与它值相同的位置为\(aft_i\),那么对于一个 ...

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

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

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

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

  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 可持久化KDtree/二维线段树

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

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

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

随机推荐

  1. 自然语言处理工具HanLP-基于层叠HMM地名识别

    本篇接上一篇内容<HanLP-基于HMM-Viterbi的人名识别原理介绍>介绍一下层叠隐马的原理. 首先说一下上一篇介绍的人名识别效果对比: 1. 只有Jieba识别出的人名 准确率极低 ...

  2. Spark学习一:Spark概述

    1.1 什么是Spark ​ Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎. ​ 一站式管理大数据的所有场景(批处理,流处理,sql) ​ spark不涉及到数据的存储,只 ...

  3. MVCC原理 4步 什么是MVCC、事务ACID、事物隔离级别、Innodb存储引擎是如何实现MVCC的

    MVCC是来处理并发的问题,提高并发的访问效率,读不阻塞写.事物A 原子性C 一致性I 隔离性D 持久性高并发的场景下的问题脏读不可重复读幻读事物隔离级别RU读未提交 脏读/不可重复读/幻读 .不适用 ...

  4. php验证手机号记录

    看完就忘记录一下 正则: $roue = "/^1[3-9]\d{9}$/"; 前后/...... / 是正则必须的规则 ^1 : 手机号的必须是1开头   ^: 字符串开始的地方 ...

  5. nasm 使用总结

    1,编译 nasm -f bin myfile.asm -o myfile  生成目标文件 nasm -f bin myfile.asm -l myfile   生成清单文件 2,快速开始 nasm是 ...

  6. 怎样获取当前文档所有的元素节点(即html标签节点)

    方法1. 使用 document.getElementsByTagName("*"); 方法2. 使用document.querySelectorAll("*" ...

  7. Unity 更改鼠标指针

    1. 把鼠标指针图标导入到Unity中,把它的Texture Type改为Cursor : 2. 打开PlayerSettings面板,把鼠标指针图片拖到Default Cursor中: 3. 在场景 ...

  8. boost random library的使用

      生成满足一定分布的随机数,是统计模拟.系统仿真等应用中最基本的要求.matlab中提供了函数可以生成各种常见分布的随机数,c++使用boost random库也可以很容易实现. 一.例子 boos ...

  9. 4. Java入门程序

    以eclipse为例,建立一个简单的Java程序. 首先启动eclipse,进入到如下主页面: 新建一个项目,选择“File-New-Java Project”: 弹出了一个如下页面,假设命名为Tes ...

  10. python之字符串类型的格式化

    python之字符串类型的格式化 要点:python字符串通过format()方法进行格式化处理.(Python语言同时支持两种字符串格式化方法,一种类似C语言中printf()函数的格式化方法,支持 ...