一开始以为是一道搜索树的模板题,但是一看数据量10^8不能直接暴力搞了,之后就写了一篇巨长的代码,想了一下把top出的节点建树可以解决, 一开始想复杂了,导致我写了splay,SBT,hash,敲完代码手指头都有点抽了(o(╯□╰)o),后来看别人的题解发现都是离散化+离线解决的,而且只用splay就可以了,但是已经敲了这么长的代码,不忍心放弃,只好硬着头皮在线搞,还好都解决了,最后在求rank的时候遇到了一点障碍,如果有Rank i , i <= size, size为top出的不同数字个数,的时候可以直接在splay中找到排名为i的节点并把splay到树根,输出其中的记录的数字即可,然而i > size时,并不是很好搞,因为人的编号为1, 2, ..., n ,所以当没有top的时候直接输出i即可,如果有top的时候,就要判断一下大于等于i的数字有多少被top到前面去了,用i减去这些数的个数,然后还要判断一下top的数字中大于等于现在的i小于上一个i 的数字个数,然后再减去,以此循环直到数字个数为0,仅一次rank操作的最坏的复杂度是O(n*logn),后来在sbt里谢了个回溯fun函数可以解决这个问题,最后还不错1A了
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <utility> #include <ctime> using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::istringstream; using std::getline; using std::make_pair; using std::greater; const int MAXN(100010); const int MOD(1313131); template<typename T> struct SBT { struct NODE { T key; int size; NODE *left, *right; }; NODE pool[MAXN]; NODE *root, *NIL, *rear; T tkey; void init() { NIL = pool; NIL->left = NIL->right = NIL; NIL->size = 0; rear = pool+1; root = NIL; } void newnode(NODE *&sour, const T &value) { rear->key = value; rear->size = 1; rear->left = rear->right = NIL; sour = rear++; } void left_rotate(NODE *&sour) { NODE *temp = sour->right; sour->right = temp->left; temp->left = sour; temp->size = sour->size; sour->size = sour->left->size+sour->right->size+1; sour = temp; } void right_rotate(NODE *&sour) { NODE *temp = sour->left; sour->left = temp->right; temp->right = sour; temp->size = sour->size; sour->size = sour->left->size+sour->right->size+1; sour = temp; } void maintain(NODE *&sour, bool flag) { if(flag == false) { if(sour->left->left->size > sour->right->size) right_rotate(sour); else if(sour->left->right->size > sour->right->size) { left_rotate(sour->left); right_rotate(sour); } else return; } else { if(sour->right->right->size > sour->left->size) left_rotate(sour); else if(sour->right->left->size > sour->left->size) { right_rotate(sour->right); left_rotate(sour); } else return; } maintain(sour->right, true); maintain(sour->left, false); maintain(sour, true); maintain(sour, false); } void insert(const T &value) { tkey = value; insert_(root); } void insert_(NODE *&sour) { if(sour == NIL) { newnode(sour, tkey); return; } ++sour->size; if(tkey < sour->key) insert_(sour->left); else insert_(sour->right); maintain(sour, tkey >= sour->key); } NODE *search(const T &value) { NODE *sour = root; while(root != NIL && sour->key != value) { if(value < sour->key) sour = sour->left; else sour = sour->right; } return sour; } int rank(const T &value) { NODE *sour = root; int ret = 1; while(sour != NIL) { if(value <= sour->key) sour = sour->left; else { ret += sour->left->size+1; sour = sour->right; } } return ret; } NODE *successor(const T& value) { tkey = value; return successor(root); } NODE *successor_(NODE *sour) { if(sour == NIL) return NIL; if(tkey < sour->key) { NODE *temp = successor_(sour->left); if(temp == NIL) return sour; else return temp; } else { return successor_(sour->right); } } int tv; int ret; int fun(int value) { tv = value; fun_(root); return tv; } void fun_(NODE *sour) { if(sour == NIL) return; if(tv <= sour->key.num) { tv -= sour->right->size+1; fun_(sour->left); } else { fun_(sour->right); if(tv <= sour->key.num) { tv -= 1; fun_(sour->left); } } } }; struct SPLAY_TREE { struct NODE { int num; int size; NODE *fa; NODE *ch[2]; }; NODE pool[MAXN]; NODE *root, *NIL, *rear; NODE *ll, *rl; inline void push_up(NODE *sour) { sour->size = sour->ch[0]->size+sour->ch[1]->size+1; } void init() { NIL = pool; NIL->fa = NIL->ch[0] = NIL->ch[1] = NIL; NIL->size = 0; rear = pool+1; newnode(root, NIL, -1); newnode(root->ch[1], root, -1); ll = root; rl = root->ch[1]; push_up(rl); push_up(ll); } void newnode(NODE *&sour, NODE *f, int tn) { rear->num = tn; rear->fa = f; rear->ch[0] = rear->ch[1] = NIL; rear->size = 1; sour = rear++; } void rotate(NODE *sour, int flag) { NODE *f = sour->fa; f->ch[!flag] = sour->ch[flag]; sour->ch[flag]->fa = f; sour->fa = f->fa; if(f->fa != NIL) f->fa->ch[f->fa->ch[1] == f] = sour; sour->ch[flag] = f; f->fa = sour; push_up(f); } void splay(NODE *sour, NODE *goal) { while(sour->fa != goal) { if(sour->fa->fa == goal) rotate(sour, sour->fa->ch[0] == sour); else { NODE *f = sour->fa; int flag = (f->fa->ch[0] == f); if(f->ch[flag] == sour) rotate(sour, !flag); else rotate(f, flag); rotate(sour, flag); } } push_up(sour); if(goal == NIL) root = sour; } NODE *extreme(NODE *sour, int flag) { while(sour->ch[flag] != NIL) sour = sour->ch[flag]; return sour; } NODE *insert(int tn) { splay(ll, NIL); splay(rl, root); NODE *temp = extreme(rl, 0); newnode(temp->ch[0], temp, tn); splay(temp->ch[0], NIL); return root; } void erase(NODE *sour) { splay(sour, NIL); NODE *p1, *p2; p1 = extreme(sour->ch[0], 1); p2 = extreme(sour->ch[1], 0); splay(p1, NIL); splay(p2, root); p2->ch[0] = NIL; push_up(p2); push_up(p1); } NODE *select(int r) { NODE *sour = root; while(r != sour->ch[0]->size+1) { if(r <= sour->ch[0]->size) sour = sour->ch[0]; else { r -= sour->ch[0]->size+1; sour = sour->ch[1]; } } splay(sour, NIL); return root; } }; struct HASH { struct NODE { int num; NODE *next; }; NODE *head[MOD]; NODE pool[MAXN]; NODE *rear; void init() { memset(head, 0, sizeof(head)); rear = pool; } inline int hash(int num) { return num%MOD; } void insert(int num) { int h = hash(num); for(NODE *i = head[h]; i; i = i->next) if(i->num == num) return; rear->num = num; rear->next = head[h]; head[h] = rear++; } bool search(int num) { int h = hash(num); for(NODE *i = head[h]; i; i = i->next) if(i->num == num) return true; return false; } }; struct ELE { int num; SPLAY_TREE::NODE *ptr; ELE() {} ELE(int tn, SPLAY_TREE::NODE *tp): num(tn), ptr(tp) {} friend bool operator < (const ELE &op1, const ELE &op2) { return op1.num < op2.num; } friend bool operator >= (const ELE &op1, const ELE &op2) { return op1.num >= op2.num; } friend bool operator <= (const ELE &op1, const ELE &op2) { return op1.num <= op2.num; } friend bool operator == (const ELE &op1, const ELE &op2) { return op1.num == op2.num; } friend bool operator != (const ELE &op1, const ELE &op2) { return op1.num != op2.num; } }; SBT<ELE> sbt; SPLAY_TREE spt; HASH hash_table; int main() { int T; scanf("%d", &T); char str[10]; int op; int n_case(0); while(T--) { sbt.init(); spt.init(); hash_table.init(); int N, Q; printf("Case %d:\n", ++n_case); scanf("%d%d", &N, &Q); for(int i = 0; i < Q; ++i) { scanf("%s%d", str, &op); if(str[0] == 'T') { if(hash_table.search(op)) { SBT<ELE>::NODE *p = sbt.search(ELE(op, NULL)); spt.erase(p->key.ptr); p->key.ptr = spt.insert(op); } else { hash_table.insert(op); SPLAY_TREE::NODE *p = spt.insert(op); sbt.insert(ELE(op, p)); } } else if(str[0] == 'Q') { if(hash_table.search(op)) { SBT<ELE>::NODE *p = sbt.search(ELE(op, NULL)); spt.splay(p->key.ptr, spt.NIL); printf("%d\n", spt.root->ch[0]->size); } else { int temp = sbt.rank(ELE(op, NULL)); printf("%d\n", op+(sbt.root->size-(temp-1))); } } else { if(op <= sbt.root->size) { SPLAY_TREE::NODE *p = spt.select(op+1); printf("%d\n", p->num); } else { // int temp = sbt.rank(ELE(op, NULL)); // int ret = op-(sbt.root->size-(temp-1)); // while(hash_table.search(ret)) // --ret; printf("%d\n", sbt.fun(op)); } } } } return 0; }