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] ...
随机推荐
- 转载:ensemble计划和数据库
原文来源:x2yline在生信进化树上的评论,http://www.biotrainee.com/thread-626-1-1.html Ensemble( ensembl.org网站是常用真核生物参 ...
- JQuery 操作 iframe
JQuery访问iframe内的元素 $("iframe#Main", top.document).contents().find("#id"); JQuery ...
- spring+springmvc+mybatis(ssm)
1.jdbc.properties jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/jk ...
- MapReduce-边数据
边数据 边数据(side data)是作业所需的额外的只读数据,以辅助处理主数据集.所面临的挑战在于如何使所有map或reduce任务(这些任务散布在集群内部)都能够方便而高效地使用边数据. 利用Jo ...
- MapReduce-读取文件写入HBase
MapReduce直接写入HBase 代码如下 package com.hbase.mapreduce; import java.io.IOException; import org.apache.c ...
- linux中动态链接库的创建与使用
LINUX系统中动态链接库的创建与使用 http://www.cnblogs.com/ardar/articles/357321.html 正常C源文件编写,编译时-shared即可得到SO, gcc ...
- wpf 界面平级之间设置上下顺序关系(ZIndex)
只能用于平级之间设置上下顺序 this.grid1.SetValue(Grid.ZIndexProperty, 9999); Panel.SetZIndex(th ...
- Python爬虫之利用BeautifulSoup爬取豆瓣小说(三)——将小说信息写入文件
#-*-coding:utf-8-*- import urllib2 from bs4 import BeautifulSoup class dbxs: def __init__(self): sel ...
- GIT 应用gitreview方式提交代码过程
t status -- 是不是修改的文件 git diff (文件名) -- 看文件修改位置 git add (文件名的空格串) git commit -- 提交到本地 git stash -- 暂存 ...
- android实现异步的问题小经验总结
1.如下图所言,必须在UI线程中调用异步任务的子类 2.经过碰壁 测试 --.方法一中 @Override public void onClick(DialogInterface dialog, in ...