BZOJ 3489: A simple rmq problem KDtree
Description
因为是OJ上的题,就简单点好了。给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大。如果找不到这样的数,则直接输出0。我会采取一些措施强制在线。
Input
第一行为两个整数N,M。M是询问数,N是序列的长度(N<=100000,M<=200000)
第二行为N个整数,描述这个序列{ai},其中所有1<=ai<=N
再下面M行,每行两个整数x,y,
询问区间[l,r]由下列规则产生(OIER都知道是怎样的吧>_<):
l=min((x+lastans)mod n+1,(y+lastans)mod n+1);
r=max((x+lastans)mod n+1,(y+lastans)mod n+1);
Lastans表示上一个询问的答案,一开始lastans为0
Output
一共M行,每行给出每个询问的答案。
题解: 对于一个区间 $[l,r]$ 一个数只出现依次说明上次出现在 $[1,l-1]$ 中(或没出现),下一次出现在 $[r+1,n]$ 中(或没出现).
直接维护一个 3 维 $KDtree$ 即可.
第一维维护 $pre_{i}$,第二位维护 $i$ 本身,第三维维护下一次出现的位置.
每次按照上述条件直接进行数点即可.
思路还是非常巧妙的.
#include<bits/stdc++.h>
#define maxn 200000
#define inf 100000000
#define mid ((l+r)>>1)
#define lson (t[x].ch[0])
#define rson (t[x].ch[1])
using namespace std;
void setIO(string s)
{
string in=s+".in";
freopen(in.c_str(),"r",stdin);
}
int n,Q,lastans,d,_ans;
int lst[maxn],nex[maxn],pos[maxn],arr[maxn];
struct Node
{
int ch[2],minv[3],maxv[3],p[3],w,_max;
}t[maxn];
bool cmp(Node a,Node b)
{
if(a.p[d]==b.p[d] && a.p[(d+1)%3]==b.p[(d+1)%3]) return a.p[(d+2)%3] < b.p[(d+2)%3];
if(a.p[d]==b.p[d]) return a.p[(d+1)%3] < b.p[(d+1)%3];
return a.p[d] < b.p[d];
}
void pushup(int x,int y)
{
for(int i=0;i<3;++i)
{
t[x].minv[i]=min(t[x].minv[i],t[y].minv[i]);
t[x].maxv[i]=max(t[x].maxv[i],t[y].maxv[i]);
}
t[x]._max=max(t[x]._max,t[y]._max);
}
int build(int l,int r,int o)
{
d=o;
nth_element(t+l,t+mid,t+1+r,cmp);
for(int i=0;i<3;++i) t[mid].minv[i]=t[mid].maxv[i]=t[mid].p[i];
t[mid].ch[0]=t[mid].ch[1]=0;
t[mid]._max=t[mid].w;
if(mid>l)
{
t[mid].ch[0]=build(l,mid-1,(o+1)%3);
pushup(mid,t[mid].ch[0]);
}
if(r>mid)
{
t[mid].ch[1]=build(mid+1,r,(o+1)%3);
pushup(mid,t[mid].ch[1]);
}
return mid;
}
int isout(int x,int l,int r)
{
if(t[x].minv[0] >= l || t[x].maxv[2] <= r || t[x].minv[1] > r || t[x].maxv[1] < l) return 1;
return 0;
}
int isin(int x,int l,int r)
{
if(t[x].maxv[0] < l && t[x].minv[2] > r && t[x].minv[1] >= l && t[x].maxv[1] <= r) return 1;
return 0;
}
void query(int x,int l,int r)
{
if(isout(x, l, r)) return;
if(isin(x, l, r))
{
_ans=max(_ans, t[x]._max);
return;
}
if(t[x].p[0] < l && t[x].p[1] >= l && t[x].p[1] <= r && t[x].p[2] > r) _ans=max(_ans, t[x].w);
if(lson && t[lson]._max > _ans) query(lson, l, r);
if(rson && t[rson]._max > _ans) query(rson, l, r);
}
int main()
{
int i,j,x,y,root,a;
// setIO("input");
scanf("%d%d",&n,&Q);
for(i=1;i<=n;++i)
{
scanf("%d",&a);
nex[pos[a]]=i, lst[i]=pos[a], pos[a]=i, arr[i]=a;
}
for(i=1;i<=n;++i)
{
t[i].p[0]=lst[i], t[i].p[1]=i, t[i].p[2] = nex[i] ? nex[i] : n + 1, t[i].w=arr[i];
}
root=build(1,n,0);
while(Q--)
{
scanf("%d%d",&x,&y);
x=(x+lastans) % n + 1;
y=(y+lastans) % n + 1;
if(x > y) swap(x, y);
_ans = -inf;
query(root, x, y);
lastans = (_ans == -inf ? 0 : _ans);
printf("%d\n",lastans);
}
return 0;
}
BZOJ 3489: A simple rmq problem KDtree的更多相关文章
- BZOJ 3489 A simple rmq problem ——KD-Tree
考前写写板子. 用$(i,pre[i],nxt[i])$来描述一个点,然后就变成了区间求最值的问题. KD-Tree 由低维转向高维的方法,可以用来敲暴力. 剩下就是KD-Tree的基本操作了. #i ...
- BZOJ 3489: A simple rmq problem (KD-tree做法)
KD树水过这道可持久化树套树-其实就是个三维偏序 题解戳这里 CODE #include <bits/stdc++.h> using namespace std; #define ls ( ...
- BZOJ 3489: A simple rmq problem
3489: A simple rmq problem Time Limit: 40 Sec Memory Limit: 600 MBSubmit: 1594 Solved: 520[Submit] ...
- 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][ ...
- [BZOJ 3489] A simple rmq problem 【可持久化树套树】
题目链接:BZOJ - 3489 题目分析 “因为是OJ上的题,就简单点好了.”——出题人 真的..好..简单... 首先,我们求出每个数的前一个与它相同的数的位置,即 prev[i] ,如果前面没有 ...
- BZOJ 3489 A simple rmq problem 可持久化KDtree/二维线段树
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3489 题意概述: 给出一个序列,每次询问一个序列区间中仅出现了一次的数字最大是多少,如果 ...
- bzoj 3489 A simple rmq problem - 线段树
Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直 ...
- bzoj 3489 A simple rmq problem——主席树套线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3489 题解:http://www.itdaan.com/blog/2017/11/24/9b ...
- BZOJ 3489 A simple rmq problem(可持久化线段树)
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3489 题意:一个数列.每次询问一个区间内出现一次的最大的数字是多少. 思路:设la ...
随机推荐
- Linux内核之于红黑树and AVL树
为什么Linux早先使用AVL树而后来倾向于红黑树? 实际上这是由红黑树的有用主义特质导致的结果,本短文依旧是形而上的观点.红黑树能够直接由2-3树导出.我们能够不再提红黑树,而仅仅提2- ...
- jqury+css实现可弹出伸缩层
1.使用可弹出伸缩窗调整了之前的页面布局,使用这样的布局使整个界面看起来更加清爽也更简洁 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L ...
- poj 3020 Antenna Placement(二分无向图 匈牙利)
Antenna Placement Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6438 Accepted: 3176 ...
- hdu 5325 Crazy Bobo dfs
// hdu 5325 Crazy Bobo // // 题目大意: // // 给你一棵树,树上每一个节点都有一个权值w,选择尽可能多的节点, // 这些节点相互联通,而且依照权值升序排序之后得到节 ...
- 【bzoj1196】[HNOI2006]公路修建问题
二分答案 验证有一种贪心的思想,就是如果这条路的c1比二分的值还小,那就要果断选择一级公路. 搜过一遍后,如果可供选择的一级公路小于k,就可以直接返回否了. 接下来继续选择,如果可以选到n-1条路,就 ...
- java多线程——线程通信
一.线程通信目标 1.线程通信的目标是使线程间能够互相发送信号 2.线程通信使线程能够等待其他线程的信号 二.几种方式 1.通过共享对象 2.忙等待 线程 B 运行在一个循环里,以等待信号 (不释放c ...
- maven 国内完整源
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...
- [python基础]xml_rpc远程调控supervisor节点进程
supervisor提供的两种管理方式,supervisorctl和web其实都是通过xml_rpc来实现的. xml_rpc其实就是本地可以去调用远端的函数方法,在python中只需要引入xmlrp ...
- 小HY的四元组
4.7 比赛T1,然而这题爆零了 其实很简单的...其实哈希都不用 所以首先记录每组的差值,按其sort一下再暴力找即可 #include<cstdio> #include<iost ...
- Codeforces 792D
题意:给定一棵拥有n个节点的满二叉树(即n==2^x-1),q个查询,每次给出一个节点的编号,再给出一个由L,R,U组成的字符串序列,依次表示向左子节点.右子节点.父节点移动,如果移动不合法,则忽略. ...