In this problem, you have to maintain a dynamic set of numbers which support the two fundamental operations
- INSERT(S,x): if x is not in S, insert x into S
- DELETE(S,x): if x is in S, delete x from S
and the two type of queries
- K-TH(S) : return the k-th smallest element of S
- COUNT(S,x): return the number of elements of S smaller than x
Input
- Line 1: Q (1 ≤ Q ≤ 200000), the number of operations
- In the next Q lines, the first token of each line is a character I, D, K or C meaning that the corresponding operation is INSERT, DELETE, K-TH or COUNT, respectively, following by a whitespace and an integer which is the parameter for that operation.
If the parameter is a value x, it is guaranteed that 0 ≤ |x| ≤ 109. If the parameter is an index k, it is guaranteed that 1 ≤ k ≤ 109.
Output
For each query, print the corresponding result in a single line. In particular, for the queries K-TH, if k is larger than the number of elements in S, print the word 'invalid'.
Example
Input 8 I -1 I -1 I 2 C 0 K 2 D -1 K 1 K 2 Output 1 2 2 invalid
PS:这道题我原本用运算符重载,结果超时了。。
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; struct Node { Node * ch[2]; int r,v,s; bool operator < (const Node & a) const { return r < a.r; } int cmp(int x) const { if(x == v) return -1; return x < v?0:1; } void maintain() { s = 1; if(ch[0] != NULL) s += ch[0] -> s; if(ch[1] != NULL) s += ch[1] -> s; } }*root; void rotate(Node *&o,int d) { Node * k = o -> ch[d^1]; o -> ch[d^1] = k -> ch[d]; k -> ch[d] = o; o -> maintain(); k -> maintain(); o = k; } void insert(Node *& o,int x) { if(o == NULL) { o = new Node(); o -> ch[0] = o -> ch[1] = NULL; o -> v = x; o -> r = rand(); o -> s = 1; } else { int d = o -> cmp(x); insert(o -> ch[d],x); if(o -> ch[d] -> r > o -> r) rotate(o,d^1); } o -> maintain(); } void remove(Node *& o,int x) { int d = o -> cmp(x); if(d == -1) { Node * tmp = o; if(o -> ch[0] == NULL) { o = o -> ch[1]; delete tmp; tmp = NULL; } else if(o -> ch[1] == NULL) { o = o -> ch[0]; delete tmp; tmp = NULL; } else { int d2 = (o -> ch[0] -> r > o -> ch[1] -> r?1:0); rotate(o,d2); remove(o -> ch[d2],x); } } else remove(o -> ch[d],x); if(o != NULL) o -> maintain(); } bool find(Node * o,int x) { while(o != NULL) { int d = o -> cmp(x); if(d == -1) return 1; else o = o -> ch[d]; } return 0; } int Rank(Node * o,int x) { int ans = 0; while(o) { if(o -> v == x) { if(o -> ch[0]) ans += o -> ch[0] -> s; return ans; } else if(o -> v > x) { o = o -> ch[0]; } else { if(o -> ch[0]) ans += o -> ch[0] -> s; ans++; o = o -> ch[1]; } } return ans; } int Kth(Node *o,int k)//这里是要返回第k小的元素 { while(k) { if(o -> ch[0]) { if(o -> ch[0] -> s >= k) o = o -> ch[0]; else if( o -> ch[0] -> s == k-1) return o -> v; else k -= o-> ch[0] -> s + 1,o = o -> ch[1]; } else if( k == 1 ) return o -> v; else k--,o = o -> ch[1]; } } void DeleteTreap(Node *& o) { if(o == NULL) return; if(o -> ch[0] != NULL) DeleteTreap(o -> ch[0]); if(o -> ch[1] != NULL) DeleteTreap(o -> ch[1]); delete o; o = NULL; } int main() { //freopen("in.txt","r",stdin); int n; scanf("%d",&n); root = NULL; char ope[5];int num; for(int i = 0;i < n;i++) { scanf("%s%d",ope,&num); if(ope[0] == 'I') { if(!find(root,num)) insert(root,num); } else if(ope[0] == 'D') { if(find(root,num)) remove(root,num); } else if(ope[0] == 'C')//比num小的数 { printf("%d\n",Rank(root,num)); } else { if(root && root -> s >= num) { int tmp = Kth(root,num); printf("%d\n",tmp); } else printf("invalid\n"); } } DeleteTreap(root); return 0; }