题意:
找第K大的数
分析:
可以用STL里的priority_queue解决,这里尝试使用AVL树~
//AC CODE:
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int delta; const int INF = 10000000; template<typename T> class AVL { public: AVL() { pp = pool; TMP = node(0,0,NULL,NULL); MYNULL = &TMP; roof = MYNULL; } void insert(T k) { insert(roof,k); } void erase(T k) { erase(roof,k); } bool empty() { return roof == MYNULL; } int findK(int k) { if(k <= 0) return -INF; return findK(roof,k); } struct node { node *lchild,*rchild; T value; int h,size;//h表示高度,size表示以当前节点为跟的子树有多少个节点 node() {} node (int h,int size,node * lchild,node *rchild) { this->size = size; this->h = h; this->lchild = lchild; this->rchild = rchild; } }; node* roof; private: #define max(a,b) ((a) < (b) ? (b) : (a)) static const int N = 1000000; node* MYNULL,TMP; //为了快速方便的求高度而设立的虚空节点 node pool[N],*pp; int findK(node* &R,int k) { if(k == R->lchild->size + 1) return R->value; else if(k <= R->lchild->size) return findK(R->lchild,k); else if(k > R->size - R->rchild->size) return findK(R->rchild,k + R->rchild->size - R->size); } //旋转前维护该节点的子树的height和size,然后才能根据更新的数据,判断该树是否平衡,然后旋转 //该函数维护了平衡树的数据域 void fix(node* &R) { R->h = max(R->rchild->h,R->lchild->h) + 1; R->size = R->rchild->size + R->lchild->size + 1; } void rightsinglerotate(node* &R)//LL型旋转,单旋一次 { node * lc = R->lchild; R->lchild = lc->rchild; fix(R); lc->rchild = R; R = lc; fix(R); } void leftsinglerotate(node* &R)//RR型旋转,单选一次 { node * rc = R->rchild; R->rchild = rc->lchild; fix(R); rc->lchild = R; R = rc; fix(R); } void leftdoublerotate(node* &R)//RL型旋转,双旋 { rightsinglerotate(R->rchild); leftsinglerotate(R); } void rightdoublerotate(node* &R)//LR型旋转,双旋 { leftsinglerotate(R->lchild); rightsinglerotate(R); } void maintain(node* &R)//维护平衡 { if(R->lchild != MYNULL) { if(R->lchild->lchild->h == R->rchild->h + 1) rightsinglerotate(R); else if(R->lchild->rchild->h == R->rchild->h + 1) rightdoublerotate(R); } if(R->rchild != MYNULL) { if(R->rchild->rchild->h == R->lchild->h + 1) leftsinglerotate(R); else if(R->rchild->lchild->h == R->lchild->h + 1) leftdoublerotate(R); } } void insert(node* &R,T value) { if(R == MYNULL) { R = mynew(value); return; } else if(value <= R->value) insert(R->lchild,value); else if(value > R->value) insert(R->rchild,value); fix(R); maintain(R); } //找到该节点后, //如果该节点R没有右儿子,直接删除,把他的左子树R->child接到他的父节点即可。 //如果有右儿子,那就找到他右子树中最小的元素的节点tmp, //把他放到当前节点R->value = tmp->value。再以他的右子树为根递归的删除tmp->value;递归完右子树维护数据域。 //最后在调整树使其不失衡。 void erase(node* &R,T value) { if(R == MYNULL) return; if(R->value == value) { if(R->rchild == MYNULL) { node * tmp = R; R = tmp->lchild; } else { node *tmp = R->rchild; while(tmp->lchild != MYNULL) tmp = tmp->lchild; R->value = tmp->value; erase(R->rchild,tmp->value); fix(R); } return; } else if(value < R->value) erase(R->lchild,value); else if(value < R->value) erase(R->rchild,value); fix(R); maintain(R); } node* mynew(T value) { pp->lchild = pp->rchild = MYNULL; pp->size = pp->h = 1; pp->value = value; return pp++; } #undef max }; AVL<int> avltree; int main() { int n,k,tmp; char cmd; while(scanf("%d %d",&n,&k)!=EOF) { getchar(); while(!avltree.empty()) { avltree.erase(avltree.roof->value); } for(int i=0;i<n;i++) { scanf("%c",&cmd); if(cmd=='I') { scanf("%d",&tmp); avltree.insert(tmp); } else { int tmp = avltree.findK(avltree.roof->size - k + 1); if(tmp == -INF) printf("-1\n"); else printf("%d\n",tmp); } getchar(); } } return 0; }