【BZOJ3489】A simple rmq problem【kd树】
题意
给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大。如果找不到这样的数,则直接输出0。我会采取一些措施强制在线。
分析
预处理出pre[i],nxt[i]分别代表左边离它最近的相同数字的坐标,nxt[i]代表右边离它最近的相同数组的坐标。那么我们每次查询在[l,r]内,找出一个最大的数字且它的pre[i]<l,nxt[i]>r。我们如何用kd树解决这个问题呢?我们用三维的kd树来处理,第一维为下标i,第二维为pre[i],第三维为nxt[i],val为它本身的值。那么我们每次查询都是在一个长方体内查询最大的val就可以了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream> using namespace std;
const int maxn=1e5+;
const int INF=;
int a[maxn],pre[maxn],nxt[maxn],last[maxn];
struct kdNode{
int x[],mnn[],mxn[];
int lc,rc;
int val,maxv;
}p[maxn],q;
int n,m,cmpNo,root;
int cmp(kdNode a,kdNode b){
return a.x[cmpNo]<b.x[cmpNo];
}
void maintain(int o){
int l=p[o].lc,r=p[o].rc;
for(int i=;i<;i++){
p[o].mnn[i]=min(min(p[l].mnn[i],p[r].mnn[i]),p[o].x[i]);
p[o].mxn[i]=max(max(p[l].mxn[i],p[r].mxn[i]),p[o].x[i]);
}
p[o].maxv=max(max(p[l].maxv,p[r].maxv),p[o].val);
}
void build(int&o,int l,int r,int d){
if(l>r){
o=;
return;
}
int m=l+(r-l)/;
cmpNo=d,o=m;
nth_element(p+l,p+m,p+r+,cmp);
build(p[o].lc,l,m-,(d+)%);
build(p[o].rc,m+,r,(d+)%);
maintain(o);
}
int ans,l,r;//查询l<=x[0]<=r,x[1]<=l,x[2]>=r 空间内的最大值,这时候的kd树感觉就是高维线段树
bool all(int o){
if(p[o].mxn[]<=r&&p[o].mnn[]>=l&&p[o].mxn[]<l&&p[o].mnn[]>r)
return true;
return false;
}
bool have(int o){
if(p[o].mnn[]<=r&&p[o].mxn[]>=l&&p[o].mnn[]<l&&p[o].mxn[]>r)
return true;
return false;
} void query(int o,int d){
if(!o){
return;
}
if(all(o)){
ans=max(ans,p[o].maxv);
return;
}
// ans=max(ans,p[o].val);
if(p[o].x[]<=r&&p[o].x[]>=l&&p[o].x[]<l&&p[o].x[]>r)
ans=max(ans,p[o].val); int lc=p[o].lc,rc=p[o].rc;
if(p[lc].maxv<p[rc].maxv){
if(all(rc)){
ans=max(ans,p[rc].maxv);
}else if(have(rc)){
query(rc,(d+)%);
}
if(ans<p[lc].maxv){
if(all(lc))
ans=max(ans,p[lc].maxv);
else if(have(lc))
query(lc,(d+)%);
}
}else{
if(all(lc)){
ans=max(ans,p[lc].maxv);
}else if(have(lc)){
query(lc,(d+)%);
}
if(ans<p[rc].maxv){
if(all(rc))
ans=max(ans,p[rc].maxv);
else if(have(rc))
query(rc,(d+)%);
}
}
} int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
if(last[a[i]])
pre[i]=last[a[i]];
else
pre[i]=;
last[a[i]]=i;
}
memset(last,,sizeof(last));
for(int i=n;i>=;i--){
if(last[a[i]])
nxt[i]=last[a[i]];
else
nxt[i]=n+;
last[a[i]]=i;
} for(int i=;i<=n;i++){
p[i].x[]=i;
p[i].x[]=pre[i];
p[i].x[]=nxt[i];
p[i].val=a[i];
//printf("%d %d %d\n",p[i].x[0],p[i].x[1],p[i].x[2]);
}
for(int i=;i<;i++){
p[].mnn[i]=INF;
p[].mxn[i]=-INF;
} build(root,,n,);
int lastans=;
for(int i=;i<=m;i++){
int L,R;
scanf("%d%d",&L,&R);
l=min((L+lastans)%n+,(R+lastans)%n+);
r=max((L+lastans)%n+,(R+lastans)%n+);
// printf("%d %d\n",l,r);
ans=;
query(root,);
printf("%d\n",ans);
lastans=ans;
}
return ;
}
【BZOJ3489】A simple rmq problem【kd树】的更多相关文章
- 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][ ...
- 【bzoj3489】 A simple rmq problem k-d树
由于某些原因,我先打了一个错误的树套树,后来打起了$k-d$.接着因不明原因在思路上被卡了很久,在今天中午蹲坑时恍然大悟...... 对于一个数字$a_i$,我们可以用一组三维坐标$(i,pre,nx ...
- BZOJ3489 A simple rmq problem K-D Tree
传送门 什么可持久化树套树才不会写呢,K-D Tree大法吼啊 对于第\(i\)个数,设其前面最后的与它值相同的位置为\(pre_i\),其后面最前的与它值相同的位置为\(aft_i\),那么对于一个 ...
- BZOJ3489 A simple rmq problem 【可持久化树套树】*
BZOJ3489 A simple rmq problem Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一 ...
- 【题解】BZOJ3489 A Hard RMQ problem(主席树套主席树)
[题解]A simple RMQ problem 占坑,免得咕咕咕了,争取在2h内写出代码 upd:由于博主太菜而且硬是要用指针写两个主席树,所以延后2hQAQ upd:由于博主太菜而且太懒所以他决定 ...
- bzoj3489 A simple rmq problem 可持久化树套树
先预处理出两个个数组pre,next.pre[i]表示上一个与i位置数字相同的位置,若不存在则设为0:next[i]表示下一个与i位置数字相同的位置,若不存在则设为n+1.那么一个满足在区间[L,R] ...
- bzoj3489: A simple rmq problem (主席树)
//========================== 蒟蒻Macaulish:http://www.cnblogs.com/Macaulish/ 转载要声明! //=============== ...
- 【kd-tree】bzoj3489 A simple rmq problem
Orz zyf教给蒟蒻做法 蒟蒻并不会这题正解……(可持久化树套树?...Orz 对于每个点,我们可以求出pre[i],nex[i],那么询问的答案就是:求max (a[i]),其中 i 满足(pre ...
- bzoj 3489 A simple rmq problem - 线段树
Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直 ...
- BZOJ.3489.A simple rmq problem(主席树 Heap)
题目链接 当时没用markdown写,可能看起来比较难受...可以复制到别的地方看比如DevC++. \(Description\) 给定一个长为n的序列,多次询问[l,r]中最大的只出现一次的数.强 ...
随机推荐
- 高级浏览器-SRWare Iron 29.0.1600.0 版本发布
SRWare Iron是德国一安全公司srware改造的Chrome(铬)命名为铁(iron)的浏览器.于2008年9月18日首次发布. 据官方介绍,Iron浏览器砍掉了Chromium原程序中的很多 ...
- 2018.12.7 L190
China called for the immediate release of Meng Wanzhou, chief financial officer of Huawei Technologi ...
- 通过Ftp put命令上传导致文件损坏的解决办法
通过Linux命令行向在一台Windows FTP服务器上传文件.然后在另一台Windows客户机登录FTP服务器下载,但是下载后的文件大小变了,exe文件错误了不能正确执行.刻意打包的文件(.rar ...
- ThinkTemplate模板引擎的设计和使用方法
在PHP开发的过程中,我们会接触到很多的模板引擎,包括FastTemplate.SmartTemplate.Smarty.tinybutstrong等,通常都是为了满足MVC开发模式的表现层需要,让显 ...
- Mysql查询正在运行的事务以及杀掉它
查询 正在执行的事务:SELECT * FROM information_schema.INNODB_TRX 根据这个事务的线程ID(trx_mysql_thread_id): 可以使用mysql命令 ...
- 接口测试工具Soapui5.1.2参数化之Properties20150924
上次用天气预报的来给大家演示了下如何创建项目.测试套件.测试用例的操作,今天演示下如何参数化,废话不多说,跟着操作即可: 1.在一个用例中有两个步骤,我们想将第一个步骤中的响应中的值,传入第二个步骤中 ...
- [爬虫] 学Scrapy,顺便把它的官方教程给爬下来
想学爬虫主要是因为算法和数据是密切相关的,有数据之后可以玩更多有意思的事情,数据量大可以挖掘挖掘到更多的信息. 之前只会通过python中的request库来下载网页内容,再用BeautifulSou ...
- java模板导出PDF
本次完善综合特点: 一对一,点对点的给对应的地方写值,比如模板里面放了个name标识,在程序里把“张三”赋给name,那么输出的pdf里面name的地方就变成了张三,准确方便快捷 支持中文,可以使用自 ...
- SqlServer高级特性--游标
游标 用途:在数据很多的时候,如果在java代码中进行循环之后再进行更新数据,会造成频繁的连接数据库,耗费性能,所以就可以使用到游标 作用:查询出来的集合直接在SQL中进行遍历在进行更新 DECLAR ...
- [LeetCode系列] 变序词查找问题(Anagrams)
给定一系列词, 找出其中所有的变序词组合. Note: 变序词 - 组成字符完全相同但次序不同的单词. 如dog和god, ate和eat. 算法描述: 使用map<string, vector ...