TYVJ1728
裸的平衡树,直接做,练习代码能力。
注意查询rank时等价于查有多少个比它小的;
虽然建树是小于当前节点key值的放在左子树,但是因为maintain可能使得左子树任意key值不满足严格小于当前节点的key值,所以查询时(如查询第k大,前继,后继)仍需key值小于等于当前节点的key值时就搜索左子树。
具体看代码。
寻找x的前继时,若是x大于当前节点key值,则当前节点也可能是x的前继,所以如果在右子树递归找不到更优的前继时,当前节点则为x前继的前继。(else中的if判断)
inline int Pred(int t,int v)
{
if (!t) return INF;
if (v <= key[t]) return Pred(left[t],v);
else
{
int temp = Pred(right[t],v);
if (temp == INF) return key[t];
else return temp;
}
}
后继类似
CODE:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 1000000000
using namespace std;
const int maxn = 2000005;
int N,T,tot;
int left[maxn],right[maxn],size[maxn],key[maxn];
inline void L_rotate(int &t)
{
int k = right[t];
right[t] = left[k];
left[k] = t;
size[k] = size[t];
size[t] = size[left[t]] + size[right[t]] + 1;
t = k;
}
inline void R_rotate(int &t)
{
int k = left[t];
left[t] = right[k];
right[k] = t;
size[k] = size[t];
size[t] = size[left[t]] + size[right[t]] + 1;
t = k;
}
inline void maintain(int &t,bool flag)
{
if (!flag)
{
if (size[left[left[t]]] > size[right[t]])
R_rotate(t);
else if (size[right[left[t]]] > size[right[t]])
L_rotate(left[t]), R_rotate(t);
else return;
} else
{
if (size[right[right[t]]] > size[left[t]])
L_rotate(t);
else if (size[left[right[t]]] > size[left[t]])
R_rotate(right[t]), L_rotate(t);
else return;
}
maintain(left[t],0);
maintain(right[t],1);
maintain(t,0);
maintain(t,1);
}
inline void Insert(int &t,int v)
{
if (!t)
{
t = ++ tot;
size[t] = 1;
left[t] = right[t] = 0;
key[t] = v;
} else
{
size[t] ++;
if (v < key[t]) Insert(left[t],v);
else Insert(right[t],v);
maintain(t,v >= key[t]);
}
}
inline int Delete(int &t,int v)
{
size[t] --;
if ((key[t] == v) || (v < key[t] && !left[t]) || (v >= key[t] && !right[t]))
{
int ret = key[t];
if (!left[t] || !right[t]) t = left[t] + right[t];
else key[t] = Delete(left[t],key[t]+1);
return ret;
}
if (v < key[t]) return Delete(left[t],v);
else return Delete(right[t],v);
}
inline int Rank(int t,int v)
{
if (!t) return 0;
if (v <= key[t]) return Rank(left[t],v);
else return size[left[t]] + 1 + Rank(right[t],v);
}
inline int Select(int t,int v)
{
int temp = size[left[t]] + 1;
if (temp == v) return key[t];
if (v <= temp) return Select(left[t],v);
else return Select(right[t],v-temp);
}
inline int Pred(int t,int v)
{
if (!t) return INF;
if (v <= key[t]) return Pred(left[t],v);
else
{
int temp = Pred(right[t],v);
if (temp == INF) return key[t];
else return temp;
}
}
inline int Succ(int t,int v)
{
if (!t) return INF;
if (v >= key[t]) return Succ(right[t],v);
else
{
int temp = Succ(left[t],v);
if (temp == INF) return key[t];
else return temp;
}
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
scanf("%d",&N);
while (N--)
{
int op,x;
scanf("%d%d",&op,&x);
if (op == 1) Insert(T,x);
if (op == 2) Delete(T,x);
if (op == 3) printf("%d\n",Rank(T,x)+1);
if (op == 4) printf("%d\n",Select(T,x));
if (op == 5) printf("%d\n",Pred(T,x));
if (op == 6) printf("%d\n",Succ(T,x));
}
return 0;
}