BZOJ - 3489 KD树 范围计数 空间思维转换
题意:给定数列\(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树 范围计数 空间思维转换的更多相关文章
- BZOJ - 4066 KD树 范围计数 暴力重构
题意:单点更新,大矩阵(\(n*n,n≤10^5\))求和 二维的KD树能使最坏情况不高于\(O(N\sqrt{N})\) 核心在于query时判断当前子树维护的区间是否有交集/当前子节点是否在块中, ...
- BZOJ 1211: [HNOI2004]树的计数( 组合数学 )
知道prufer序列就能写...就是求个可重集的排列...先判掉奇怪的情况, 然后答案是(N-2)!/π(d[i]-1)! -------------------------------------- ...
- bzoj 1211: [HNOI2004]树的计数 -- purfer序列
1211: [HNOI2004]树的计数 Time Limit: 10 Sec Memory Limit: 162 MB Description 一个有n个结点的树,设它的结点分别为v1, v2, ...
- BZOJ - 2648 KD树 最近点查询
省赛后躺尸几天又回来更新了,内容是说好的KD树.. 具体操作从代码中感受一下 感觉已经把KD树尽量封装好了(虽然全局的D看着极不顺眼) 需要注意的是估值函数的判断条件 #include<bits ...
- BZOJ 1211 HNOI2004 树的计数 Prufer序列
题目大意:给定一棵树中全部点的度数,求有多少种可能的树 Prufer序列.详细參考[HNOI2008]明明的烦恼 直接乘会爆long long,所以先把每一个数分解质因数.把质因数的次数相加相减.然后 ...
- bzoj 3244: [Noi2013]树的计数
Description 我们知道一棵有根树可以进行深度优先遍历(DFS)以及广度优先遍历(BFS)来生成这棵树的DFS序以及BFS序.两棵不同的树的DFS序有可能相同,并且它们的BFS序也有可能相同, ...
- BZOJ 1211[HNOI2004]树的计数 - prufer数列
描述 一个有n个结点的树,设它的结点分别为v1, v2, …, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, …, dn,编程需要输出满足d(vi) ...
- 【刷题】BZOJ 1211 [HNOI2004]树的计数
Description 一个有n个结点的树,设它的结点分别为v1, v2, -, vn,已知第i个结点vi的度数为di,问满足这样的条件的不同的树有多少棵.给定n,d1, d2, -, dn,编程需要 ...
- bzoj 1211: [HNOI2004]树的计数
prufer的应用.. 详细见这篇博客:https://www.cnblogs.com/dirge/p/5503289.html import java.math.BigInteger; import ...
随机推荐
- 解决在Python中使用Win32api报错的问题,No module named win32api
一.系统环境 操作系统: Win7 64位 Python:3.7.0 二.在使用import win32api时,报错:No module named win32api 网上查到有下面解决办法: 方法 ...
- Ubuntu16.04 ARM 编译 编译器版本和unordered_map map问题
源文件内使用unordered_map时候,例如如下demo #include <unordered_map> void foo(const std::unordered_map<i ...
- intval()函数
获取变量的整数值 1.转换前转化后 原因:
- 4、MemorySubSystem
1.概述 S3C6410X存储器子系统包括7个存储器控制器,SROM控制器,两个OneNAND控制器,一个NAND Flash控制器,一个CF控制器,一个DRAM控制器.静态存储器控制器,oneNAN ...
- Date3.19
1.正则表达式的定义及使用2.Date类的用法3.Calendar类的用法========================================================1正则表达式的 ...
- Join导致冗余数据引起慢SQL
业务过程中碰到多个join引起慢SQL问题,数据量不大,但查询很慢,搜到一片BLog,参考解决. 业务过程不记录,以blog内容重现: 原SQL: select distinct abc.pro_co ...
- 编写高质量代码改善C#程序的157个建议——建议34:为泛型参数设定约束
建议34:为泛型参数设定约束 “约束”这个词可能会引起歧义,有些人肯能认为对泛型参数设定约束是限制参数的使用,实际情况正好相反.没有“约束”的泛型参数作用很有限,倒是“约束”让泛型参数具有了更多的行为 ...
- spring的介绍
Spring是什么: Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用!!! Spring是一个轻量级的控制反转(Io ...
- maven的pom文件解析及配置
1.IDEA中的Maven的pom.xml文件,其实比较通俗点介绍功能主要项目引入的jar包,管理配置项目以及一些插件的配置等项目 2.对于pom配置详细介绍,整理如下2篇文档介绍的比较系统全面: h ...
- 关于对SwfUpload的改造
Swfupload 在普通上传下,对于IE chrome firefox等有很好的兼容性. 但一旦与其他控件组合,很容易出现无法上传,帮顶事件丢失的情况. 例如Layer与Swfupload,上传一个 ...