BZOJ3489 A simple rmq problem 【可持久化树套树】*
BZOJ3489 A simple rmq problem
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行,每行给出每个询问的答案。
Sample Input
10 10
6 4 9 10 9 10 9 4 10 4
3 8
10 1
3 4
9 4
8 1
7 8
2 9
1 1
7 3
9 9
Sample Output
4
10
10
0
0
10
0
4
0
4
还是吐槽一下BZOJ的土豆(评测机),什么数组开小了显示WA,数组开大一点就CE,这可真是友好,请问RE呢?MLE呢?????????
然后讲讲这题思路
一开始看到以为是树套树套树
蒙圈了
想了⑩分钟无果然后就去看题解
结果发现可以用排序的方法把三维降成两维
只不过嘛。需要可持久化
不过我们不虚
可持久化树套树不就是在可持久化线段树上多加一句插入吗理直气壮
首先我们考虑一个数在区间内出现一次的充要条件是什么
1.l<=posi<=r" role="presentation">1.l<=posi<=r1.l<=posi<=r
2.l>prei" role="presentation">2.l>prei2.l>prei
3.r<nxti" role="presentation">3.r<nxti3.r<nxti
其中pos表示位置,pre和nxt分别表示上一个和下一个这个数出现的位置
很妙啊
我们考虑以pre为键值排序
然后我们发现我们查询的区间变成了一个前缀
所以就将pre可持久化一下
然后我们又发现nxt也是我们的限制条件
所以我们在外层的树上以nxt为下标,所以查询就变成了在线段树上查询后缀
但是还有pos的限制怎么办?
所以就把内层树搞成原序列的位置就好了
然后查询的时候非常套路地二分一下pre的位置,剩下的该怎么查怎么查
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int ans=0,w=1;char c=getchar();
while(!isdigit(c)&&c!='-')c=getchar();
if(c=='-')w=-1,c=getchar();
while(isdigit(c))ans=(ans<<1)+(ans<<3)+c-'0',c=getchar();
return ans*w;
}
#define N 100010
int n,m,lastans=0;
struct Node{int val,pos,pre,nxt;}p[N];
bool cmp(Node a,Node b){return a.pre<b.pre;}
//inside 原序列顺序
int ld[N*350],rd[N*350],maxv[N*350];
int cnt=0;
void insert(int &t,int last,int l,int r,int pos,int vl){
t=++cnt;
maxv[t]=max(vl,maxv[last]);
if(l==r)return;
ld[t]=ld[last];
rd[t]=rd[last];
int mid=(l+r)>>1;
if(pos<=mid)insert(ld[t],ld[last],l,mid,pos,vl);
else insert(rd[t],rd[last],mid+1,r,pos,vl);
}
int query(int t,int l,int r,int L,int R){
if(!t)return 0;
if(L<=l&&r<=R)return maxv[t];
int mid=(l+r)>>1;
if(R<=mid)return query(ld[t],l,mid,L,R);
if(L>mid)return query(rd[t],mid+1,r,L,R);
return max(query(ld[t],l,mid,L,R),query(rd[t],mid+1,r,L,R));
}
//outside nxt顺序
int rt[N*20],lc[N*20],rc[N*20],tot=0;
void insert(int &t,int last,int l,int r,int key,int pos,int vl){
t=++tot;
insert(rt[t],rt[last],1,n,pos,vl);
if(l==r)return;
lc[t]=lc[last];
rc[t]=rc[last];
int mid=(l+r)>>1;
if(key<=mid)insert(lc[t],lc[last],l,mid,key,pos,vl);
else insert(rc[t],rc[last],mid+1,r,key,pos,vl);
}
int query(int t,int l,int r,int L,int R,int ql,int qr){
if(!t)return 0;
if(L<=l&&r<=R)return query(rt[t],1,n,ql,qr);
int mid=(l+r)>>1;
if(R<=mid)return query(lc[t],l,mid,L,R,ql,qr);
if(L>mid)return query(rc[t],mid+1,r,L,R,ql,qr);
return max(query(lc[t],l,mid,L,R,ql,qr),query(rc[t],mid+1,r,L,R,ql,qr));
}
int outrt[N];
int pre[N],nxt[N];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)p[i].pos=i,scanf("%d",&p[i].val);
for(int i=1;i<=n;i++)pre[i]=0,nxt[i]=n+1;
for(int i=1;i<=n;i++)p[i].pre=pre[p[i].val],pre[p[i].val]=i;
for(int i=n;i>=1;i--)p[i].nxt=nxt[p[i].val],nxt[p[i].val]=i;
//for(int i=1;i<=1000;i++)cout<<i<<" "<<p[i].pre<<" "<<p[i].nxt<<endl;
sort(p+1,p+n+1,cmp);
for(int i=1;i<=n;i++)//持久化pre的顺序
insert(outrt[i],outrt[i-1],1,n+1,p[i].nxt,p[i].pos,p[i].val);
for(int i=1;i<=m;i++){
int l,r;
scanf("%d%d",&l,&r);
l=(l+lastans)%n+1;
r=(r+lastans)%n+1;
if(l>r)swap(l,r);
int ql=1,qr=n,tmp=0;
while(ql<=qr){
int mid=(ql+qr)>>1;
if(p[mid].pre<l)ql=mid+1,tmp=mid;
else qr=mid-1;
}
printf("%d\n",lastans=query(outrt[tmp],1,n+1,r+1,n+1,l,r));
}
return 0;
}
BZOJ3489 A simple rmq problem 【可持久化树套树】*的更多相关文章
- bzoj3489 A simple rmq problem 可持久化树套树
先预处理出两个个数组pre,next.pre[i]表示上一个与i位置数字相同的位置,若不存在则设为0:next[i]表示下一个与i位置数字相同的位置,若不存在则设为n+1.那么一个满足在区间[L,R] ...
- 【kd-tree】bzoj3489 A simple rmq problem
Orz zyf教给蒟蒻做法 蒟蒻并不会这题正解……(可持久化树套树?...Orz 对于每个点,我们可以求出pre[i],nex[i],那么询问的答案就是:求max (a[i]),其中 i 满足(pre ...
- BZOJ3489 A simple rmq problem K-D Tree
传送门 什么可持久化树套树才不会写呢,K-D Tree大法吼啊 对于第\(i\)个数,设其前面最后的与它值相同的位置为\(pre_i\),其后面最前的与它值相同的位置为\(aft_i\),那么对于一个 ...
- bzoj3489: A simple rmq problem (主席树)
//========================== 蒟蒻Macaulish:http://www.cnblogs.com/Macaulish/ 转载要声明! //=============== ...
- BZOJ3489: A simple rmq problem
设$i$的前驱为$p_i$,后继为$q_i$,把询问看成点$(L,R)$,有贡献的$i$满足$L\in(p_i,i]$且$R\in[i,q_i)$,询问的就是覆盖这个点的矩形的最大值.那么可以用可持久 ...
- BZOJ 3489 A simple rmq problem 可持久化KDtree/二维线段树
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3489 题意概述: 给出一个序列,每次询问一个序列区间中仅出现了一次的数字最大是多少,如果 ...
- BZOJ 3489 A simple rmq problem(可持久化线段树)
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3489 题意:一个数列.每次询问一个区间内出现一次的最大的数字是多少. 思路:设la ...
- [BZOJ 3489] A simple rmq problem 【可持久化树套树】
题目链接:BZOJ - 3489 题目分析 “因为是OJ上的题,就简单点好了.”——出题人 真的..好..简单... 首先,我们求出每个数的前一个与它相同的数的位置,即 prev[i] ,如果前面没有 ...
- 【bzoj3489】 A simple rmq problem k-d树
由于某些原因,我先打了一个错误的树套树,后来打起了$k-d$.接着因不明原因在思路上被卡了很久,在今天中午蹲坑时恍然大悟...... 对于一个数字$a_i$,我们可以用一组三维坐标$(i,pre,nx ...
随机推荐
- zlib编译方法
点击这里下载zlib1.2.8源码 http://www.zlib.net/fossils/ ##编译方法一## - 解压源码文件到指定目录,例如 x:\zlib - 打开VS2015的Develop ...
- 使用ssm整合是项目启动tomcat报错java.lang.IndexOutOfBoundsException
解决办法:删除.m2文件夹下的全部仓库,然后重启myeclipse,对项目进行maven project.问题解决. 在没有这样做时,除了tomcat启动会失败,项目还有会报如下错误: ①cvc-co ...
- 在Web API 2 中实现带JSON的Patch请求
译文:http://www.cnblogs.com/kexxxfeng/p/the-patch-verb-in-web-api-2-with-json.html 原文:https://carly.io ...
- 转载:Chrome 控制台不完全指南
Chrome的开发者工具已经强大到没朋友的地步了,特别是其功能丰富界面友好的console,使用得当可以有如下功效: 更高「逼格」更快「开发调试」更强「进阶级的Frontender」 Bug无处遁形「 ...
- C++(三十三) — 全局函数、成员函数的区别
区别: (1)全局函数的参数个数,比局部函数要多一个: (2)二者都可,返回元素.返回引用. class test { public: test(int a, int b) { this->a ...
- 大小堆C++实现
C++大小堆实现(仿函数) 具体代码如下 #pragma once #include<iostream> #include<vector> using namespace st ...
- Attribute 'items' must be an array, a Collection or a Map错误解决!
唉!真的要说一句话叫做论一串代码的重要性!就是如此的气人!气的牙根痒痒! 前几天刚刚写过SpringMVC之ModelAndView的 jsp值在浏览页面不显示的问题!也是因为这一串代码,但是这一次一 ...
- 1-15-2-RAID5 企业级RAID磁盘阵列的搭建(RAID1、RAID5、RAID10)
RAID5的搭建 第一步:添加四个磁盘,开机并检查(略过) 第二步:使用fdisk命令分别对四个磁盘进行分区,效果如下图: 第三步:使用mdadm命令创建RAID5磁盘阵列 [root@localho ...
- 修改Pycharm for Mac背景色
Mac 上面的Pycharm的背景是白色,太刺眼,网上教程那么多,实用性都不高,最终在csdn找到了一个. 修改步骤如下: pycharm -->Preferences --> Appea ...
- php中mysql_fetch_row() 和mysql_fetch_array之间有什么区别
mysql_fetch_row是从结果集取出1行数组,作为枚举 mysql_fetch_array是从结果集取出一行数组作为关联数组,或数字数组,两者兼得eg:$sql="select ab ...