题意:给定数列\(a[1...n]\),\(Q\)次查询\([L,R]\)中只出现一次的最大值

这道题的做法比较劲..

对每个元素构造三维空间的点\((i,pre[i],next[i])\),查询\([L,R]\)可以转换为查询\((L≤x≤R,y<L,z>R)\)的区间的最大值

就是说前一个和后一个都不在这个范围内的值

除此以外要注意剪枝!直接按照上面的思路码是会T的

比如随机乱跑,估计一下子树的\(max\)是否比当前答案更优,或者估价边界是否应该搜索(后者我没有写,也就慢个4s..)

#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)(a))
#define println(a) printf("%lld\n",(ll)(a))
#define printbk(a) printf("%lld ",(ll)(a))
using namespace std;
const int MAXN = 1e5+11;
const int INF = 0x7fffffff;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int D;
struct Point{
int x[3],val;
bool operator < (const Point &rhs) const{
return x[D]<rhs.x[D];
}
};
struct KD{
int son[MAXN][2],lx[MAXN][3],rx[MAXN][3];
int size[MAXN];
int mx[MAXN];
Point p[MAXN];
int root,tot;
void pu(int o){
mx[o]=p[o].val;
int lc=son[o][0],rc=son[o][1];
rep(i,0,2){
lx[o][i]=rx[o][i]=p[o].x[i];
if(lc){
if(mx[lc]>mx[o]) mx[o]=mx[lc];
if(lx[lc][i]<lx[o][i]) lx[o][i]=lx[lc][i];
if(rx[lc][i]>rx[o][i]) rx[o][i]=rx[lc][i];
}
if(rc){
if(mx[rc]>mx[o]) mx[o]=mx[rc];
if(lx[rc][i]<lx[o][i]) lx[o][i]=lx[rc][i];
if(rx[rc][i]>rx[o][i]) rx[o][i]=rx[rc][i];
}
}
size[o]=1+size[lc]+size[rc];
}
void init(int n){
root=D=0; tot=n;
}
inline bool inside(int o,int l,int r){
return lx[o][2]>r&&rx[o][1]<l&&lx[o][0]>=l&&rx[o][0]<=r;
}
inline bool outside(int o,int l,int r){
return lx[o][0]>r||rx[o][0]<l||lx[o][1]>=l||rx[o][2]<=r;
}
inline bool in(int o,int l,int r){
int x=p[o].x[0],y=p[o].x[1],z=p[o].x[2];
return x>=l&&x<=r&&y<l&&z>r;
}
/*注意必要的剪枝!*/
// ll query(int o,int l,int r){// l<=x<=r && y<l && z>r //上一个<l 下一个>r
// if(!o) return 0;
// if(inside(o,l,r)) return mx[o];
// if(outside(o,l,r)) return 0;
// ll res=0;
// if(in(o,l,r)) res=p[o].val;
// return max(res,max(query(son[o][0],l,r),query(son[o][1],l,r)));
// }
/*上面这个会T*/
int ANS;
void query(int o,int l,int r){
if(!o) return;
if(inside(o,l,r)){
if(ANS<mx[o]) ANS=mx[o];
return;
}
if(outside(o,l,r)) return;
if(in(o,l,r)&&ANS<p[o].val) ANS=p[o].val;
int lc=son[o][0], rc=son[o][1];
if(mx[lc]>mx[rc]){
if(mx[lc]>ANS) query(lc,l,r); //其实还可以对左右子树多加一个估价函数
if(mx[rc]>ANS) query(rc,l,r);
}else{
if(mx[rc]>ANS) query(rc,l,r);
if(mx[lc]>ANS) query(lc,l,r);
}
}
int build(int now,int l,int r){
int mid=l+r>>1; son[mid][0]=son[mid][1]=0;
D=now; nth_element(p+l,p+mid,p+r+1);
mx[mid]=p[mid].val; size[mid]=1;
rep(i,0,2) lx[mid][i]=rx[mid][i]=p[mid].x[i];
if(l<mid) son[mid][0]=build((now+1)%3,l,mid-1);
if(r>mid) son[mid][1]=build((now+1)%3,mid+1,r);
pu(mid); return mid;
}
ll query(int l,int r){
ANS=0;
query(root,l,r);
return ANS;
}
}kd;
int a[MAXN],pre[MAXN],nxt[MAXN];
int main(){
ll n,m,lastans=0;
while(cin>>n>>m){
rep(i,1,n) pre[i]=-1;
rep(i,1,n) nxt[i]=n+1;
rep(i,1,n) a[i]=read();
rep(i,1,n){
kd.p[i].x[0]=i;
kd.p[i].val=a[i];
kd.p[i].x[1]=pre[a[i]];
pre[a[i]]=i;
}
rrep(i,n,1){
kd.p[i].x[2]=nxt[a[i]];
nxt[a[i]]=i;
}
kd.init(n); kd.root=kd.build(0,1,n);
rep(i,1,m){
int x=read();
int y=read();
int l=min((x+lastans)%n+1,(y+lastans)%n+1);
int r=max((x+lastans)%n+1,(y+lastans)%n+1);
ll res=kd.query(l,r);
println(res);
lastans=res;
}
}
return 0;
}

BZOJ - 3489 KD树 范围计数 空间思维转换的更多相关文章

  1. BZOJ - 4066 KD树 范围计数 暴力重构

    题意:单点更新,大矩阵(\(n*n,n≤10^5\))求和 二维的KD树能使最坏情况不高于\(O(N\sqrt{N})\) 核心在于query时判断当前子树维护的区间是否有交集/当前子节点是否在块中, ...

  2. BZOJ 1211: [HNOI2004]树的计数( 组合数学 )

    知道prufer序列就能写...就是求个可重集的排列...先判掉奇怪的情况, 然后答案是(N-2)!/π(d[i]-1)! -------------------------------------- ...

  3. bzoj 1211: [HNOI2004]树的计数 -- purfer序列

    1211: [HNOI2004]树的计数 Time Limit: 10 Sec  Memory Limit: 162 MB Description 一个有n个结点的树,设它的结点分别为v1, v2, ...

  4. BZOJ - 2648 KD树 最近点查询

    省赛后躺尸几天又回来更新了,内容是说好的KD树.. 具体操作从代码中感受一下 感觉已经把KD树尽量封装好了(虽然全局的D看着极不顺眼) 需要注意的是估值函数的判断条件 #include<bits ...

  5. BZOJ 1211 HNOI2004 树的计数 Prufer序列

    题目大意:给定一棵树中全部点的度数,求有多少种可能的树 Prufer序列.详细參考[HNOI2008]明明的烦恼 直接乘会爆long long,所以先把每一个数分解质因数.把质因数的次数相加相减.然后 ...

  6. bzoj 3244: [Noi2013]树的计数

    Description 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序.两棵不同的树的DFS序有可能相同,并且它们的BFS序也有可能相同, ...

  7. BZOJ 1211[HNOI2004]树的计数 - prufer数列

    描述 一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, …, dn,编程需要输出满足d(vi) ...

  8. 【刷题】BZOJ 1211 [HNOI2004]树的计数

    Description 一个有n个结点的树,设它的结点分别为v1, v2, -, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, -, dn,编程需要 ...

  9. bzoj 1211: [HNOI2004]树的计数

    prufer的应用.. 详细见这篇博客:https://www.cnblogs.com/dirge/p/5503289.html import java.math.BigInteger; import ...

随机推荐

  1. the install of mysql in Linux System

    一.下载MySql 浏览器打开 https://www.mysql.com/downloads/mysql/#downloads 下载 我下载的版本是Red Hat 5 版本的 https://www ...

  2. GO程序设计2——面向过程基础知识

    1 简介 GO语言google开发的新语言.有如下特性: 自动垃圾回收.更丰富的内置数据类型.函数多返回值.错误处理.匿名函数和闭包.类型和接口.并发编程.反射.多语言混合编程 package mai ...

  3. 【原创】请不要对Boost Format使用Byte作为参数

    曾几何时我们可以肆无忌惮的对sprintf传入BYTE等类型作为参数,只要你指定的为%D即可打印出对应的数字 但是boost format不可以,当你发生类型截断,错误,异常,请尽快查看你传入的类型是 ...

  4. 手机APP兼容性测试

    兼容性测试方案 兼容性问题 屏幕分辨率兼容性问题 软件(iOS和Android系统版本及不同厂家的定制ROM)兼容性问题 硬件(不同的CPU.内存大小等等)兼容性问题 网络(2G/3G/4G/WIFI ...

  5. ios7 设置status bar风格

    How to change status bar style during launch on iOS 7 up vote4down votefavorite   When I launch my a ...

  6. Diameter协议摘要

    ---------选择同学整理文档 1.   协议概述 Diameter协议主要为应用程序提供认证.鉴权.计费框架,即AAA,并支持本地AAA和漫游场景下的AAA. 1.1.  特点介绍 以前的AAA ...

  7. .net Reflection(反射)- 二

    反射 Reflection 中访问方法 新建一个ClassLibrary类库: public class Student { public string Name { get; set; } publ ...

  8. HTML5移动Web开发实战 PDF扫描版​

    <HTML5移动Web开发实战>提供了应对这一挑战的解决方案.通过阅读本书,你将了解如何有效地利用最新的HTML5的那些针对移动网站的功能,横跨多个移动平台.全书共分10章,从移动Web. ...

  9. 使用JS完成首页定时弹出广告图片

    一.需求分析 在首页中的顶部做一个定时弹出广告图片. 二.技术分析 隐藏图片: display: none        定时操作: setInterval(“显示图片的函数”, 3000); 三.代 ...

  10. struts2中错误提示:There is no Action mapped for namespace / and action name

    当在struts2中运行时出现如上所述错误时: 1.在src目录下创建struts.xml一定要注意拼写 2.struts.xml文件中引入和extend是否正确 3.在web.xml 中<we ...