BZOJ3489:A simple rmq problem
浅谈\(K-D\) \(Tree\):https://www.cnblogs.com/AKMer/p/10387266.html
题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=3489
主席树套主席树写法:https://www.cnblogs.com/AKMer/p/10197640.html
可以同主席树套主席树写法一样,用可持久化搞掉第一维\(pre\),然后对于\(n\)个点\((id,nxt)\),直接查询区间\([l,r][r+1,n+1]\)内的最大值即为答案。
时间复杂度:\(O(nlogn+m\sqrt{n})\)
空间复杂度:\(O(nlogn)\)
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
#define bo11 p[u].mx[0]<x1||p[u].mn[0]>x2
#define bo12 p[u].mx[1]<y1||p[u].mn[1]>y2
#define bo21 x1<=p[u].mn[0]&&p[u].mx[0]<=x2
#define bo22 y1<=p[u].mn[1]&&p[u].mx[1]<=y2
#define bo31 x1<=p[u].c[0]&&p[u].c[0]<=x2
#define bo32 y1<=p[u].c[1]&&p[u].c[1]<=y2
const int maxn=1e5+5,inf=2e9;
int pos[maxn],tmp[maxn];
int n,m,pps,lstans,x1,x2,y1,y2;
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
struct data {
int v,pre,nxt,id;
bool operator<(const data &a)const {
return pre<a.pre;
}
}a[maxn];
struct kd_tree {
int tot,root[maxn];
struct point {
int ls,rs,mxv,val,d;
int c[2],mn[2],mx[2];
bool operator<(const point &a)const {
if(c[pps]==a.c[pps])return c[0]<a.c[0];
return c[pps]<a.c[pps];
}
}p[maxn*18];
int build(int l,int r,int d) {
int mid=(l+r)>>1,u=mid;pps=d;
nth_element(p+l,p+mid,p+r+1);
if(l<mid)p[u].ls=build(l,mid-1,d^1);
if(r>mid)p[u].rs=build(mid+1,r,d^1);
p[u].d=d;return u;
}
void update(int u) {
int ls=p[u].ls,rs=p[u].rs;
int mxv=max(p[ls].mxv,p[rs].mxv);
p[u].mxv=max(mxv,p[u].val);
for(int i=0;i<2;i++) {
int mn=min(p[ls].mn[i],p[rs].mn[i]);
p[u].mn[i]=min(p[u].mn[i],mn);
int mx=max(p[ls].mx[i],p[rs].mx[i]);
p[u].mx[i]=max(p[u].mx[i],mx);
}
}
void insert(int lst,int &u,int x,int y,int v) {
u=++tot,p[u]=p[lst];
if(p[u].c[0]==x&&p[u].c[1]==y) {
p[u].val=v;
p[u].mn[0]=p[u].mx[0]=x;
p[u].mn[1]=p[u].mx[1]=y;
update(u);return;
}
int O=p[u].d,num=O?y:x;
if((num<p[u].c[O])||(num==p[u].c[O]&&x<p[u].c[0]))
insert(p[lst].ls,p[u].ls,x,y,v);
else insert(p[lst].rs,p[u].rs,x,y,v);
update(u);
}
void prepare() {
p[0].mn[0]=p[0].mn[1]=inf;
p[0].mx[0]=p[0].mx[1]=-inf;
for(int i=1;i<=n;i++) {
p[i].mn[0]=p[i].mn[1]=inf;
p[i].mx[0]=p[i].mx[1]=-inf;
p[i].c[0]=a[i].id;
p[i].c[1]=a[i].nxt;
p[i].mxv=-inf;
}
root[0]=build(1,n,0);
for(int i=1;i<=n;i++) {
insert(root[i-1],root[i],a[i].id,a[i].nxt,a[i].v);
}
}
void find(int u) {
if(p[u].mxv<lstans)return;
if(bo11||bo12)return;
if(bo21&&bo22) {lstans=max(lstans,p[u].mxv);return;}
if(bo31&&bo32) lstans=max(lstans,p[u].val);
if(p[u].ls)find(p[u].ls);
if(p[u].rs)find(p[u].rs);
}
}T;
int main() {
T.tot=n=read(),m=read();
for(int i=1;i<=n;i++) {
a[i].v=read(),a[i].id=i;
a[i].pre=pos[a[i].v],pos[a[i].v]=i;
}
for(int i=1;i<=n;i++)pos[i]=n+1;
for(int i=n;i;i--)
a[i].nxt=pos[a[i].v],pos[a[i].v]=i;
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)tmp[i]=a[i].pre;
T.prepare();
for(int i=1;i<=m;i++) {
int l=(read()+lstans)%n+1,r=(read()+lstans)%n+1;
if(r<l)swap(l,r);x1=l,x2=r,y1=r+1,y2=n+1;
int pos=lower_bound(tmp+1,tmp+n+1,l)-tmp-1;
lstans=-inf,T.find(T.root[pos]);
if(lstans==-inf)lstans=0;
printf("%d\n",lstans);
}
return 0;
}
BZOJ3489:A simple rmq problem的更多相关文章
- 【BZOJ3489】A simple rmq problem kd-tree
[BZOJ3489]A simple rmq problem Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过 ...
- 【BZOJ3489】A simple rmq problem(KD-Tree)
[BZOJ3489]A simple rmq problem(KD-Tree) 题面 BZOJ 题解 直接做肯定不好做,首先我们知道我们是一个二维平面数点,但是限制区间只能出现一次很不好办,那么我们给 ...
- 【BZOJ3489】A simple rmq problem
[BZOJ3489]A simple rmq problem 题面 bzoj 题解 这个题不强制在线的话随便做啊... 考虑强制在线时怎么搞 预处理出一个位置上一个出现的相同数的位置\(pre\)与下 ...
- 【bzoj3489】 A simple rmq problem
http://www.lydsy.com/JudgeOnline/problem.php?id=3489 (题目链接) 题意 在线求区间不重复出现的最大的数. Solution KDtree竟然能够处 ...
- 【bzoj3489】 A simple rmq problem k-d树
由于某些原因,我先打了一个错误的树套树,后来打起了$k-d$.接着因不明原因在思路上被卡了很久,在今天中午蹲坑时恍然大悟...... 对于一个数字$a_i$,我们可以用一组三维坐标$(i,pre,nx ...
- 【BZOJ3489】A simple rmq problem【kd树】
题意 给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直接输出0.我会采取一些措施强制在线. 分析 预处理 ...
- 【bzoj3489】A simple rmq problem 三维KD-tree
题目描述 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直接输出0.我会 ...
- BZOJ3489 A simple rmq problem 【可持久化树套树】*
BZOJ3489 A simple rmq problem Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一 ...
- BZOJ 3489: A simple rmq problem
3489: A simple rmq problem Time Limit: 40 Sec Memory Limit: 600 MBSubmit: 1594 Solved: 520[Submit] ...
随机推荐
- 【HackerRank】Utopian tree
The Utopian tree goes through 2 cycles of growth every year. The first growth cycle of the tree occu ...
- OpenGL帧缓存对象(FBO:Frame Buffer Object)
http://blog.csdn.net/dreamcs/article/details/7691690 转http://blog.csdn.net/xiajun07061225/article/de ...
- PCIE phy和控制器
转:https://wenku.baidu.com/view/a13bc1c20722192e4436f617.html 文章中的第11页开始有划分phy和控制器部分....
- String和StringBuilder、StringBuffer
Java平台提供了两种类型的字符串:String和StringBuffer/StringBuilder String 只读字符串,这里的只读并不是指String类型变量无法被修改,而是指String类 ...
- 基于Visual c++ 2012的php扩展开发 - HelloWord!
1.cmd进入命令行模式,并进入php-5.6.20-src/ext源代码的ext目录下输入命令php ext_skel_win32.php --extname=HelloWord,执行结果如下图: ...
- 各种排序算法-用Python实现
冒泡排序 # 冒泡排序 def bubble_sort(l): length = len(l) # 外层循环 length遍,内层循环少一遍 while length: for j in range( ...
- poj 2762 Going from u to v or from v to u?【强连通分量缩点+拓扑排序】
Going from u to v or from v to u? Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 15812 ...
- UVA 11731 Ex-circles (外切圆)
题意:给你三角形的三条边,求图中DEF的面积和阴影部分的面积. 题解:一些模板,三角形的旁切圆半径:.与 三旁心为 #include<set> #include<map> #i ...
- 对象存储API
使用对象存储API步骤: 1.购买腾讯云对象存储(COS)服务 2.在腾讯云 对象存储控制台 里创建一个Bucket 3.在控制器 个人API密钥 页里获取APPID,SecretID,SecretK ...
- shutdown TCP 端口445
一. 协议:TCP 端口:445 二. shutdown /m \\192.168.1.15 -s -t 60 net use \\192.168.1.15\ipc$ 密码 /user:账户 三. g ...