BZOJ3489 A simple rmq problem
2016-06-17 22:02
357 查看
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 106 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
410
10
0
0
10
0
4
0
4
HINT
注意出题人为了方便,input的第二行最后多了个空格。2015.6.24新加数据一组,但未重测
Source
by zhzqkkk正解:kd-tree
解题报告:
做这道题本来是为了试试可持久化线段树的,然而感觉好复杂。结果在网上突然看到一份博客,居然用的是kd-tree,当时就激动了。
参考博客:http://trinklee.blog.163.com/blog/static/2381580602015422933539/
这份博客讲的很清楚了,三维kd-tree。我们维护三个值,当前值的上一次出现位置,下一次出现位置。显然查询区间[l,r]时i满足当且仅当 last[num[i]]<l && next[num[i]]>r 时才需被计入贡献,满足要求。
那么这样的查询显然是可以用kd-tree来做的。都是老套路了,想好怎么建了就跟我之前做的两道kd-tree题一样了。还没有插入操作了,还简单些了好吗
代码如下:
//It is made by jump~ #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #ifdef WIN32 #define OT "%I64d" #else #define OT "%lld" #endif using namespace std; typedef long long LL; const int MAXN = 100011; int shu[MAXN]; int n,m; int last[MAXN]; int L[MAXN],R[MAXN]; int root; int D; int ans; int cha[3][2]; struct node{ int l,r; int Min[3],Max[3],d[3]; int num; int zhi; }a[MAXN]; inline int getint() { int w=0,q=0; char c=getchar(); while((c<'0' || c>'9') && c!='-') c=getchar(); if (c=='-') q=1, c=getchar(); while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w; } inline bool cmp(node q,node qq){ for(int i=0;i<=2;i++) if(q.d[(D+i)%3]!=qq.d[(D+i)%3]) return (q.d[(D+i)%3]<qq.d[(i+D)%3]); return 1; } inline void update(int x){ if(a[x].l) { for(int i=0;i<=2;i++) a[x].Min[i]=min(a[x].Min[i],a[a[x].l].Min[i]),a[x].Max[i]=max(a[x].Max[i],a[a[x].l].Max[i]); a[x].zhi=max(a[x].zhi,a[a[x].l].zhi); } if(a[x].r) { for(int i=0;i<=2;i++) a[x].Min[i]=min(a[x].Min[i],a[a[x].r].Min[i]),a[x].Max[i]=max(a[x].Max[i],a[a[x].r].Max[i]); a[x].zhi=max(a[x].zhi,a[a[x].r].zhi); } } inline int build_tree(int l,int r,int d){ int mid=(l+r)/2; D=d; nth_element(a+l+1,a+mid+1,a+r+1,cmp); a[mid].zhi=a[mid].num; for(int i=0;i<=2;i++) a[mid].Min[i]=a[mid].Max[i]=a[mid].d[i]; if(l!=mid) a[mid].l=build_tree(l,mid-1,(d+1)%3); if(mid!=r) a[mid].r=build_tree(mid+1,r,(d+1)%3); update(mid); return mid; } inline bool pan(int now){ for(int i=0;i<=2;i++) { if(a[now].Max[i]<cha[i][0] || a[now].Min[i]>cha[i][1]) return false; } return true; } inline void query(int now) { if(a[now].zhi<ans) return ;//剪枝 bool flag=true; for(int i=0;i<=2;i++) if(cha[i][0]>a[now].Min[i] || cha[i][1]<a[now].Max[i] ) { flag=false; break;} if(flag) { ans=max(ans,a[now].zhi); return ; } flag=true; for(int i=0;i<=2;i++) if(cha[i][0]>a[now].d[i] || cha[i][1]<a[now].d[i]) flag=false; if(flag) { ans=max(ans,a[now].num); } if(a[now].l && pan(a[now].l)) { query(a[now].l); } if(a[now].r && pan(a[now].r)) { query(a[now].r); } } inline void solve(){ n=getint(); m=getint(); for(int i=1;i<=n;i++) { shu[i]=getint(); L[i]=last[shu[i]]; last[shu[i]]=i; } for(int i=1;i<=n;i++) last[i]=n+1; for(int i=n;i>=1;i--) R[i]=last[shu[i]],last[shu[i]]=i; for(int i=1;i<=n;i++) { a[i].d[0]=i; a[i].d[1]=L[i]; a[i].d[2]=R[i]; a[i].num=shu[i]; } root=build_tree(1,n,0); int l,r,x,y; for(int i=1;i<=m;i++) { l=getint(); r=getint(); x=(l+ans)%n+1; y=(r+ans)%n+1; if(x<y) l=x,r=y; else l=y,r=x; ans=0; cha[0][0]=l; cha[0][1]=r; cha[1][0]=0; cha[1][1]=l-1; cha[2][0]=r+1; cha[2][1]=n+1; query(root); printf("%d\n",ans); } } int main() { solve(); return 0; }
相关文章推荐
- 补c++作业2
- 再次拾回android-修改系统定义的style
- SQLServer附加数据库失败
- 彩电市场竞争格局巨变, 创维“修炼内功”逆势增长
- exit和_exit,atexit的浅析
- 【翻译】Tweepy 3.5.0 Doc (2) Authentication Tutorial
- selenium常用命令之操作页面元素及获取元素内容的事件整理
- java学习笔记之ORM注解
- Deep Learning(深度学习)学习笔记整理系列之(四)
- 大道至简阅读笔记02
- 【转】Linux CentOS内核编译:下载CentOS源码、编译2.6.32-220的错误(apic.c:819 error 'numi_watchdog' undeclared)
- android 多渠道打包
- 数据结构(树,点分治):POJ 1741 Tree
- 跳出多重循环 JS
- BZOJ3245 最快路线
- Deep Dive 3 - NIO
- 学习进度条--第十六周
- 「C语言」单链表/双向链表的建立/遍历/插入/删除
- appium启动sdk的android模拟器
- 【C语言】22-枚举