题目大意:基本是一颗平衡树的基本操作。
思路:本来是Treap的题,但是为了体现出vEB树的独特用处,所以就比较卡时间。权值线段树的常数会小一点,但是还是会T,所以就只能用zkw来水过了。
只需要在求最大值最小值里面好好考虑一下,剩下就没什么好说的了。
CODE:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 1000010 #define LEFT (pos << 1) #define RIGHT (pos << 1|1) using namespace std; int range,asks,M; int tree[MAX << 2]; inline void Modify(int pos,int c) { tree[pos] += c; for(; pos; pos >>= 1) tree[pos] += c; } inline int GetMin(int pos) { if(!tree[pos]) return 0; while(pos <= M) { if(tree[LEFT]) pos = LEFT; else pos = RIGHT; } return pos - M; } inline int GetMax(int pos) { if(!tree[pos]) return 0; while(pos <= M) { if(tree[RIGHT]) pos = RIGHT; else pos = LEFT; } return pos - M; } inline int GetPred(int x) { int pos = x + M; while(1) { if(pos == 1) return 0; if(pos&1 && tree[pos^1]) return GetMax(pos^1); pos >>= 1; } return 0; } inline int GetSucc(int x) { int pos = x + M; while(1) { if(pos == 1) return 0; if(!(pos&1) && tree[pos^1]) return GetMin(pos^1); pos >>= 1; } return 0; } int main() { cin >> range >> asks; for(M = 1; M <= range; M <<= 1); for(int x,flag,i = 1; i <= asks; ++i) { scanf("%d",&flag); if(flag == 1) { scanf("%d",&x); ++x; if(!tree[M + x]) Modify(M + x,1); } else if(flag == 2) { scanf("%d",&x); ++x; if(tree[M + x]) Modify(M + x,-1); } else if(flag == 3) printf("%d\n",GetMin(1) - 1); else if(flag == 4) printf("%d\n",GetMax(1) - 1); else if(flag == 5) { scanf("%d",&x); ++x; printf("%d\n",GetPred(x) - 1); } else if(flag == 6) { scanf("%d",&x); ++x; printf("%d\n",GetSucc(x) - 1); } else { scanf("%d",&x); ++x; printf("%d\n",tree[x + M] ? 1:-1); } } return 0; }
BZOJ 3685 普通van Emde Boas树 zkw线段树
原文地址:http://blog.csdn.net/jiangyuze831/article/details/41347021