http://www.lydsy.com/JudgeOnline/problem.php?id=3489 (题目链接)

题意

  在线求区间不重复出现的最大的数。

Solution

  KDtree竟然能够处理这种问题,好神啊。

  以下转自:http://trinklee.blog.163.com/blog/static/2381580602015422933539/

  记录每个位置的数前一次出现的位置pre[i]和后一次出现的位置nxt[i],然后我们询问的就是

  1. l<=i<=r

  2. pre[i]<l

  3. nxt[i]>r

  满足三个条件下的max(a[i])

  将每个点的信息看作三维空间上带权值的点(i,pre[i],nxt[i]),然后建立kdtree。

  询问的话,等价于第一维在[l,r]范围内,第二维在[0,l-1]范围内,第三维在[r+1,+oo]范围内的一个三维空间内,查询在里面的点权最大值。于是这样就能转换成kdtree啦~

  关于kdtree:

  1. 建树跟二维的一样建法,xyz三个坐标轮流换,并且维护当前域内的点权max

  2. 查询的时候,如果当前域内max<=ans,直接不做(剪枝1),如果当前点在查询域内则更新答案,如果子空间与查询域不交则不查(剪枝2)

细节

  竟然1A了w(゚Д゚)w

代码

// bzoj3489
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#define LL long long
#define inf 1<<30
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=100010,maxm=200010;
int a[maxn],head[maxn],pre[maxn],nxt[maxn],ax[3],ay[3];
int D,n,m,rt; struct KDtree {
int l,r,val,Max,v[3],mn[3],mx[3];
friend bool operator < (const KDtree a,const KDtree b) {
return a.v[D]<b.v[D];
}
}tr[maxn]; void update(int k) {
for (int i=0;i<=2;i++) {
if (tr[k].l) {
tr[k].mx[i]=max(tr[k].mx[i],tr[tr[k].l].mx[i]);
tr[k].mn[i]=min(tr[k].mn[i],tr[tr[k].l].mn[i]);
}
if (tr[k].r) {
tr[k].mx[i]=max(tr[k].mx[i],tr[tr[k].r].mx[i]);
tr[k].mn[i]=min(tr[k].mn[i],tr[tr[k].r].mn[i]);
}
}
if (tr[k].l) tr[k].Max=max(tr[k].Max,tr[tr[k].l].Max);
if (tr[k].r) tr[k].Max=max(tr[k].Max,tr[tr[k].r].Max);
}
int build(int l,int r,int p) {
D=p;
int mid=(l+r)>>1;
nth_element(tr+l,tr+mid,tr+r+1);
if (l<mid) tr[mid].l=build(l,mid-1,(p+1)%3);
if (r>mid) tr[mid].r=build(mid+1,r,(p+1)%3);
update(mid);
return mid;
}
bool in(int x,int y,int X,int Y) {
return x>=X && y<=Y;
}
bool out(int x,int y,int X,int Y) {
return y<X || x>Y;
}
int query(int k) {
if (!k) return 0;
int flag=1,res=0;
for (int i=0;i<=2;i++) {
if (out(tr[k].mn[i],tr[k].mx[i],ax[i],ay[i])) return 0;
flag&=in(tr[k].mn[i],tr[k].mx[i],ax[i],ay[i]);
}
if (flag) return tr[k].Max; flag=1;for (int i=0;i<=2;i++) flag&=in(tr[k].v[i],tr[k].v[i],ax[i],ay[i]);
if (flag) res=tr[k].val; if (tr[tr[k].l].Max>tr[tr[k].r].Max) {
if (res<tr[tr[k].l].Max) res=max(res,query(tr[k].l));
if (res<tr[tr[k].r].Max) res=max(res,query(tr[k].r));
}
else {
if (res<tr[tr[k].r].Max) res=max(res,query(tr[k].r));
if (res<tr[tr[k].l].Max) res=max(res,query(tr[k].l));
}
return res;
} int main() {
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) {
scanf("%d",&a[i]);
int x=head[a[i]];head[a[i]]=i;
pre[i]=x;nxt[x]=i;
}
for (int i=1;i<=n;i++) {
tr[i].v[0]=tr[i].mx[0]=tr[i].mn[0]=i;
tr[i].v[1]=tr[i].mx[1]=tr[i].mn[1]=pre[i];
tr[i].v[2]=tr[i].mx[2]=tr[i].mn[2]=nxt[i] ? nxt[i] : n+1;
tr[i].val=tr[i].Max=a[i];
}
rt=build(1,n,0);
int ans=0;
for (int l,r,x,y,i=1;i<=m;i++) {
scanf("%d%d",&x,&y);
l=min((x+ans)%n+1,(y+ans)%n+1);
r=max((x+ans)%n+1,(y+ans)%n+1);
ax[0]=l,ay[0]=r;
ax[1]=0,ay[1]=l-1;
ax[2]=r+1,ay[2]=n+1;
ans=query(rt);
printf("%d\n",ans);
}
return 0;
}

【bzoj3489】 A simple rmq problem的更多相关文章

  1. 【BZOJ3489】A simple rmq problem(KD-Tree)

    [BZOJ3489]A simple rmq problem(KD-Tree) 题面 BZOJ 题解 直接做肯定不好做,首先我们知道我们是一个二维平面数点,但是限制区间只能出现一次很不好办,那么我们给 ...

  2. 【BZOJ3489】A simple rmq problem

    [BZOJ3489]A simple rmq problem 题面 bzoj 题解 这个题不强制在线的话随便做啊... 考虑强制在线时怎么搞 预处理出一个位置上一个出现的相同数的位置\(pre\)与下 ...

  3. 【BZOJ3489】A simple rmq problem kd-tree

    [BZOJ3489]A simple rmq problem Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过 ...

  4. 【bzoj3489】 A simple rmq problem k-d树

    由于某些原因,我先打了一个错误的树套树,后来打起了$k-d$.接着因不明原因在思路上被卡了很久,在今天中午蹲坑时恍然大悟...... 对于一个数字$a_i$,我们可以用一组三维坐标$(i,pre,nx ...

  5. 【BZOJ3489】A simple rmq problem【kd树】

    题意 给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直接输出0.我会采取一些措施强制在线. 分析 预处理 ...

  6. 【bzoj3489】A simple rmq problem 三维KD-tree

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

  7. 【BZOJ】【3489】A simple rmq problem

    KD-Tree(乱搞) Orz zyf教给蒟蒻做法 蒟蒻并不会这题正解……(可持久化树套树?...Orz 对于每个点,我们可以求出pre[i],nex[i],那么询问的答案就是:求max (a[i]) ...

  8. 【bzoj 3489】A simple rmq problem

    题目 \(kdt\)就是数点神器 我们先扫两遍处理出每个数上一次出现的位置\(pre_i,nxt_i\),之后变成\((i,pre_i,nxt_i)\)这样一个三维空间上的点 就变成了求一个立方体的最 ...

  9. BZOJ3489:A simple rmq problem

    浅谈\(K-D\) \(Tree\):https://www.cnblogs.com/AKMer/p/10387266.html 题目传送门:https://lydsy.com/JudgeOnline ...

随机推荐

  1. ISCSI target的两种安装方法

    1 tgt程序架构 tgt是用户态实现的iscsi target,而iet(iscsi enterprise target)是在内核态实现的target,tgt相比于iet来说,因为其用户态实现,方便 ...

  2. ajax入门简述

    ajax 全称为 “Asynchronous JavaScript and XML”(异步 JavaScript 和 XML),是一种创建交互式网页应用的网页开发技术,本质上是一个浏览器端的技术,就是 ...

  3. go语言之行--简介与环境搭建

    一.Go简介 Go 是一个开源的编程语言,它能让构造简单.可靠且高效的软件变得容易. Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后 ...

  4. python基础1之python介绍、安装、变量和字符编码、数据类型、输入输出、数据运算、循环

    开启python之路 内容概要: 一.python介绍 二.安装 三.第一个python程序 四.变量和字符编码 五.用户输入 六.数据类型 七.一切皆对象 八.数据运算 九.if else 流程判断 ...

  5. JavaEE笔记(十一)

    Spring beans使用参数占位符(JDBC配置读取示例) beans.xml配置文件 <?xml version="1.0" encoding="UTF-8& ...

  6. LHS 和 RHS----你所不知道的JavaScript系列(1)

      变量的赋值操作会执行两个动作, 首先编译器会在当前作用域中声明一个变量(如果之前没有声明过), 然后在运行时引擎会在作用域中查找该变量, 如果能够找到就会对它赋值.----<你所不知道的Ja ...

  7. 《深入浅出NodeJS》mindmap

    接触NodeJS有快两年了,但因为和我的工作内容关系不大,所以一直没有系统的学习.最近终于有空能系统地了解学习一下这门技术,于是买了一本朴灵老师的<深入浅出NodeJS>仔细研读.这本书内 ...

  8. PAT甲题题解-1095. Cars on Campus(30)-(map+树状数组,或者模拟)

    题意:给出n个车辆进出校园的记录,以及k个时间点,让你回答每个时间点校园内的车辆数,最后输出在校园内停留的总时间最长的车牌号和停留时间,如果不止一个,车牌号按字典序输出. 几个注意点: 1.如果一个车 ...

  9. 词频统计 SPEC 20160911

    本文档随时可能修改,并且没有另行通知. 请确保每一次在开始修改你的代码前,读标题中的日期,如果晚于你上次阅读, 请重读一次. 老五在寝室吹牛他熟读过<鲁滨逊漂流记>,在女生面前吹牛热爱&l ...

  10. 20135202闫佳歆--week4 课本第5章学习笔记

    第五章 系统调用 一.与内核通信 系统调用在用户控件进程和硬件设备之间添加了一个中间层,作用如下" 为用户空间提供了一种硬件的抽象接口 系统调用保证了系统的稳定和安全 每个进程都运行在虚拟系 ...