3489: A simple rmq problem K-D tree
2016-03-14 06:21
344 查看
K-D树解决一些传统的序列问题,详细解法可参见任之洲《k-d tree在传统OI数据结构题中的应用》
用lastxlast_x表示xx上次出现的位置,nextxnext_x表示xx下次出现的位置,所以要求的就是满足l≤i≤r,lastai<l,nextai>rl\leq i \leq r,last_{a_i}r的aia_i的最大值,可以看作是三维平面中的点,然后用三维k-d tree解决极值问题。
复杂度O(mn23)O(mn^{\frac{2}{3}})
用lastxlast_x表示xx上次出现的位置,nextxnext_x表示xx下次出现的位置,所以要求的就是满足l≤i≤r,lastai<l,nextai>rl\leq i \leq r,last_{a_i}r的aia_i的最大值,可以看作是三维平面中的点,然后用三维k-d tree解决极值问题。
复杂度O(mn23)O(mn^{\frac{2}{3}})
[code]#include<iostream> #include<cstdio> #include<algorithm> #define inf 1000000007 #define N 100005 using namespace std; struct node { int d[3],mn[3],mx[3]; int v,mv; }; node tree ; int ls ,rs ,pre ; int n,m,ans,root,L,R,D; inline int read() { int a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } inline bool operator<(node a,node b) { return a.d[D]<b.d[D]; } inline void pushup(int k) { for (int i=0;i<=2;i++) { tree[k].mn[i]=min(tree[k].d[i],min(tree[ls[k]].mn[i],tree[rs[k]].mn[i])); tree[k].mx[i]=max(tree[k].d[i],max(tree[ls[k]].mx[i],tree[rs[k]].mx[i])); } tree[k].mv=max(tree[k].v,max(tree[ls[k]].mv,tree[rs[k]].mv)); } void build(int &k,int l,int r,int dir) { int mid=l+r>>1; k=mid; D=dir; nth_element(tree+l,tree+mid,tree+r+1); if (l<mid) build(ls[k],l,mid-1,(dir+1)%3); if (r>mid) build(rs[k],mid+1,r,(dir+1)%3); pushup(k); } inline bool check(int k) { if (!k) return 0; if (tree[k].mn[1]>=L||tree[k].mx[2]<=R||tree[k].mx[0]<L||tree[k].mn[0]>R) return 0; return 1; } void query(int k) { if (!k) return; if (tree[k].mn[0]>=L&&tree[k].mx[0]<=R&&tree[k].mx[1]<L&&tree[k].mn[2]>R) { ans=max(ans,tree[k].mv); return; } if (tree[k].d[0]>=L&&tree[k].d[0]<=R&&tree[k].d[1]<L&&tree[k].d[2]>R) ans=max(ans,tree[k].v); if (tree[ls[k]].mv>tree[rs[k]].mv) { if (tree[ls[k]].mv>ans&&check(ls[k])) query(ls[k]); if (tree[rs[k]].mv>ans&&check(rs[k])) query(rs[k]); } else { if (tree[rs[k]].mv>ans&&check(rs[k])) query(rs[k]); if (tree[ls[k]].mv>ans&&check(ls[k])) query(ls[k]); } } int main() { for (int i=0;i<=2;i++) tree[0].mx[i]=-inf,tree[0].mn[i]=inf; n=read(); m=read(); for (int i=1;i<=n;i++) { int x=read(); tree[i].d[0]=i; tree[i].d[2]=n+1; tree[i].v=tree[i].mv=x; if (pre[x]) tree[i].d[1]=pre[x],tree[pre[x]].d[2]=i; pre[x]=i; } build(root,1,n,0); for (int i=1;i<=m;i++) { int x=read(),y=read(); L=min((x+ans)%n+1,(y+ans)%n+1); R=max((x+ans)%n+1,(y+ans)%n+1); ans=0; query(root); printf("%d\n",ans); } return 0; }
相关文章推荐
- *循环单链表
- 关于静态方法为什么不能被重写的一点思考以及overload的一些坑。
- SQL温故系列两篇(二)
- [RxJS] Wrap up
- 296. Best Meeting Point
- [leetcode] 298. Binary Tree Longest Consecutive Sequence 解题报告
- [RxJS] Sharing Streams with Share
- 求职总结
- 106. Construct Binary Tree from Inorder and Postorder Traversal
- [leetcode] 320. Generalized Abbreviation 解题报告
- Android利用Fiddler进行网络数据抓包
- 286. Walls and Gates
- 317. Shortest Distance from All Buildings
- 105. Construct Binary Tree from Preorder and Inorder Traversal
- 反思与回顾
- C++ Exceptional 最小化编译期依赖
- Leetcode 3. Longest Substring Without Repeating Characters
- vivo
- Omnispace 收藏夹
- 单例模式的常见高效实践