【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]中最大的只出现一次的数.强 ...
随机推荐
- 201621123006 《Java程序设计》第13周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 为了让你的系统可以被多个用户通过网 ...
- L198
One of the most common birth defects throughout the world is a cleft lip. Babies born with a cleft l ...
- Centos 7 系统详解
安装CentOS 7系统后,变化竟然这么大? 一.Runlevel首先一条,原来一直用的CentOS-6.5-x86_64-minimal.iso光盘镜像(400M左右无图形系统小巧便捷),而7目 ...
- jquery.cycle.js
jquery.cycle.js简单用法实例 样式: a{text-decoration: none;} *{margin:0; padding:0;} /*容器设置*/ .player { width ...
- supervisor 使用tips
Supervisor (http://supervisord.org) 是一个用 Python 写的进程管理工具,可以很方便的用来启动.重启.关闭进程,supervisor可以同时监控多个进程,并可以 ...
- Python面试题(十六)
1.取出两个升序数组中的最小的一半的元素组成一个新的升序数组. map(lambda x, y: x if x < y else y, a, b) 答案 2.用至少2种不同的方式删除一个list ...
- Struts2自定义标签3模仿原有的s:if s:elseif s:else自定义自己的if elsif else
第一步:webroot/web-inf下简历str.tld文件 <?xml version="1.0" encoding="UTF-8"?> < ...
- JavaWeb入门环境搭建
一.安装配置Tomcat 1.下载 2.配置环境变量 配置JAVA_HOME环境变量,路径为JDK的根目录 3.测试Tomcat 打开浏览器,在地址栏输入http://localhost:8080可以 ...
- Chrome Developer Tools 中的 Preview 不显示 HTML 的问题
Chrome Developer Tools 中的 Preview 不显示 HTML 的问题 最近升级到 Chrome V64,发现 Chrome Developer Tools 中的 Preview ...
- 在NOILINUX下的简易VIM配置
位置:/etc/vim/vimrc 建议使用gedit来进行配置.即使用命令:sudo gedit /etc/vim/vimrc set mouse=a " Enable mouse usa ...