由于某些原因,我先打了一个错误的树套树,后来打起了$k-d$。接着因不明原因在思路上被卡了很久,在今天中午蹲坑时恍然大悟......

对于一个数字$a_i$,我们可以用一组三维坐标$(i,pre,nxt)$来表示,其中$i$表示该数字下标,$pre$表示在区间$[1,i)$中满足$a[j]=a[i]$的最大$j$,若不存在,则$pre=0$。$nxt$表示在区间$(i,n]$中满足$a[j]=a[i]$的最小$j$,若不存在,则$nxt=n+1$。

接着我们种一棵3-d树去存储这n个点。对于任意一个节点,需存储该节点的数字,以该节点为根的字数中最大的数字,每一维的最小值和最大值。对于一组询问$[l,r]$,答案即为满足第一维在区间$[l,r]$,第二维在区间$[0,l)$,第三维在区间$(r,n+1)$中的所有点上的最大数字。在查询时,直接按照$k-d$的正常查询策略更新答案即可。

时间复杂度:$O(n log n+n^\frac{5}{3})$

警告:若采用此方法,此题建议各位加一个微小的剪枝:假定当前所得到的最大答案为$ans$,若当前访问的字树中最大答案$≤ans$,直接跳过这棵字树即可。(借助该方法极限数据耗时从17.5s降低至1.4s)

 #include<bits/stdc++.h>
#define M 210000
using namespace std;
int n,m,D,root;
struct kd{
int a[],max[],min[],now,ans,l,r;
kd(){a[]=a[]=a[]=now=l=r=;min[]=min[]=min[]=;}
kd(int xx,int yy,int zz,int kk){a[]=xx;a[]=yy;a[]=zz;now=kk;}
friend bool operator <(kd a,kd b){
return a.a[D]<b.a[D];
}
}a[M];
void upd(kd &x,kd &y){
for(int i=;i<;i++)
x.max[i]=max(x.max[i],y.max[i]),
x.min[i]=min(x.min[i],y.min[i]);
}
inline int nx(int d){if(d==) return ; return d+;}
void build(int &x,int l,int r,int d){
if(l>r) return; int mid=(l+r)>>;
D=d; nth_element(a+l,a+mid,a+r+); x=mid;
for(int i=;i<;i++) a[x].max[i]=a[x].min[i]=a[x].a[i];
build(a[x].l,l,mid-,nx(d));
build(a[x].r,mid+,r,nx(d));
upd(a[x],a[a[x].l]); upd(a[x],a[a[x].r]);
a[x].ans=max(a[x].now,max(a[a[x].l].ans,a[a[x].r].ans));
}
int ans=;
void query(int x,int l,int r){
if(x==||ans>=a[x].ans||r<a[x].min[]||a[x].max[]<l||l-<a[x].min[]||a[x].max[]<r+) return;
if(l<=a[x].min[]&&a[x].max[]<=r&&a[x].max[]<l&&r<a[x].min[])
{ans=max(ans,a[x].ans); return;}
if(l<=a[x].a[]&&a[x].a[]<=r&&a[x].a[]<l&&r<a[x].a[]) ans=max(ans,a[x].now);
query(a[x].l,l,r); query(a[x].r,l,r);
}
int last[M]={};
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
int x; scanf("%d",&x);
a[i].a[]=i; a[i].now=x;
a[i].a[]=last[x];
a[last[x]].a[]=i;
last[x]=i;
}
for(int i=;i<=n;i++) if(a[i].a[]==) a[i].a[]=n+;
build(root,,n,);
while(m--){
int x,y,l,r; scanf("%d%d",&x,&y);
l=(x+ans)%n+; r=(y+ans)%n+; if(l>r) swap(l,r);
ans=; query(root,l,r);
printf("%d\n",ans);
}
}

【bzoj3489】 A simple rmq problem k-d树的更多相关文章

  1. bzoj3489: A simple rmq problem (主席树)

    //========================== 蒟蒻Macaulish:http://www.cnblogs.com/Macaulish/  转载要声明! //=============== ...

  2. bzoj3489 A simple rmq problem 可持久化树套树

    先预处理出两个个数组pre,next.pre[i]表示上一个与i位置数字相同的位置,若不存在则设为0:next[i]表示下一个与i位置数字相同的位置,若不存在则设为n+1.那么一个满足在区间[L,R] ...

  3. BZOJ3489 A simple rmq problem 【可持久化树套树】*

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

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

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

  5. BZOJ3489: A simple rmq problem

    设$i$的前驱为$p_i$,后继为$q_i$,把询问看成点$(L,R)$,有贡献的$i$满足$L\in(p_i,i]$且$R\in[i,q_i)$,询问的就是覆盖这个点的矩形的最大值.那么可以用可持久 ...

  6. 【kd-tree】bzoj3489 A simple rmq problem

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

  7. BZOJ3489 A simple rmq problem K-D Tree

    传送门 什么可持久化树套树才不会写呢,K-D Tree大法吼啊 对于第\(i\)个数,设其前面最后的与它值相同的位置为\(pre_i\),其后面最前的与它值相同的位置为\(aft_i\),那么对于一个 ...

  8. 【BZOJ3489】A simple rmq problem

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

  9. 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][ ...

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

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

随机推荐

  1. css心得体会

    非块级元素  要使得其有长宽的效果  可以设置  margin  和  padding 块级元素     可以直接设置  width  和  height div标签   要使得你内部元素居中   可 ...

  2. 2018.07.23 codeforces 438D. The Child and Sequence(线段树)

    传送门 线段树维护区间取模,单点修改,区间求和. 这题老套路了,对一个数来说,每次取模至少让它减少一半,这样每次单点修改对时间复杂度的贡献就是一个log" role="presen ...

  3. Java中读取.properties配置文件的通用类

    由于Java中读取配置文件的代码比较固定,所以可以将读取配置文件的那部分功能单独作为一个类,以后可以复用.为了能够达到复用的目的,不能由配置文件中每一个属性生成一个函数去读取,我们需要一种通用的方法读 ...

  4. C++之类和对象的使用(三)

    对象数组 如果构造函数只有一个参数,在定义数组时可以直接在等号后面的花括号内提供.Student stud[3]={90,92,01};//合法 如果构造函数有多个参数,则不能用在定义时直接所提供所有 ...

  5. UVa 12230 && HDU 3232 Crossing Rivers (数学期望水题)

    题意:你要从A到B去上班,然而这中间有n条河,距离为d.给定这n条河离A的距离p,长度L,和船的移动速度v,求从A到B的时间的数学期望. 并且假设出门前每条船的位置是随机的,如果不是在端点,方向也是不 ...

  6. Md5 util

    Md5PasswordEncoder.java http://docs.spring.io/spring-security/site/docs/3.0.x/apidocs/org/springfram ...

  7. Paper格式-国际会议版

    Paper Title 论文题目 Authors Name/s per 1st Affiliation (Author) 作者名字/s 每第一作者 line 1 (of Affiliation): d ...

  8. 反爬虫破解系列-汽车之家利用css样式替换文字破解方法

    网站: 汽车之家:http://club.autohome.com.cn/ 以论坛为例 反爬虫措施: 在论坛发布的贴子正文中随机抽取某几个字使用span标签代替,标签内容位空,但css样式显示为所代替 ...

  9. (二进制 异或)Team Formation --ZOJ --3870

    链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3870 http://acm.hust.edu.cn/vjudge/ ...

  10. 对话框的按键处理 PreTranslateMessage、OnKeyDown和OnChar

    对话框的按键处理 PreTranslateMessage.OnKeyDown和OnChar 1.MFC对话框不能响应OnKeyDown和OnChar函数(1)现象  在MFC的对话框中,映射了WM_C ...