treap板子(洛谷 P3369 【模板】普通平衡树(Treap/SBT))
由于有相同的数,每个节点加一个权值表示此数出现的次数
1 #include<cstdio> 2 #include<cstdlib> 3 #include<ctime> 4 #include<algorithm> 5 using namespace std; 6 #define MAXI 2147483647 7 //http://blog.csdn.net/h348592532/article/details/52837228随机数 8 int rand1() 9 { 10 static int x=471; 11 return x=(48271LL*x+1)%2147483647; 12 } 13 struct Node 14 { 15 Node* ch[2]; 16 int r;//优先级 17 int v;//value 18 int size;//维护子树的节点个数 19 int num;//当前数字出现次数 20 int cmp(int x) const//要在当前节点的哪个子树去查找,0左1右 21 { 22 if(x==v) return -1; 23 return v<x;//x<v?0:1 24 } 25 void upd() 26 { 27 size=num; 28 if(ch[0]!=NULL) size+=ch[0]->size; 29 if(ch[1]!=NULL) size+=ch[1]->size; 30 } 31 }nodes[200100]; 32 int mem,n; 33 Node* root=NULL; 34 void rotate(Node* &o,int d) 35 { 36 Node* t=o->ch[d^1];o->ch[d^1]=t->ch[d];t->ch[d]=o; 37 o->upd();t->upd();//o是t子节点,一定要这个顺序upd 38 o=t;//将当前节点变成旋转完后新的父节点 39 } 40 Node* getnode() 41 { 42 return &nodes[mem++]; 43 } 44 void insert(Node* &o,int x) 45 { 46 if(o==NULL) 47 { 48 o=getnode();o->ch[0]=o->ch[1]=NULL; 49 o->v=x;o->r=rand1();o->num=1; 50 } 51 else 52 { 53 if(o->v==x) ++(o->num); 54 else 55 { 56 int d=o->v < x;//x < o->v?0:1 57 insert(o->ch[d],x); 58 if(o->r < o->ch[d]->r) rotate(o,d^1);//不是 x < o->ch[d]->r 59 } 60 } 61 o->upd(); 62 } 63 void remove(Node* &o,int x) 64 { 65 int d=o->cmp(x); 66 if(d==-1) 67 { 68 if(o->num > 0) 69 { 70 --(o->num); 71 } 72 if(o->num == 0) 73 { 74 if(o->ch[0]==NULL) o=o->ch[1]; 75 else if(o->ch[1]==NULL) o=o->ch[0]; 76 else 77 { 78 //int d2= o->ch[0]->r > o->ch[1]->r;//o->ch[0]->r > o->ch[1]->r ? 1:0 79 int d2=o->ch[1]->r < o->ch[0]->r;//o->ch[1]->r <= o->ch[0]->r 80 rotate(o,d2); 81 remove(o->ch[d2],x); 82 //左旋则原节点变为新节点的左子节点,右旋相反 83 } 84 } 85 } 86 else remove(o->ch[d],x); 87 if(o!=NULL) o->upd(); 88 } 89 bool find(Node* o,int x) 90 { 91 int d; 92 while(o!=NULL) 93 { 94 d=o->cmp(x); 95 if(d==-1) return 1; 96 else o=o->ch[d]; 97 } 98 return 0; 99 } 100 int kth(Node* o,int k) 101 { 102 if(o==NULL||k<=0||k > o->size) return 0; 103 int s= o->ch[0]==NULL ? 0 : o->ch[0]->size; 104 if(k>s&&k<=s+ o->num) return o->v; 105 else if(k<=s) return kth(o->ch[0],k); 106 else return kth(o->ch[1],k-s- o->num); 107 } 108 int rk(Node* o,int x) 109 { 110 int r=o->ch[0]==NULL ? 0 : o->ch[0]->size; 111 if(x==o->v) return r+1; 112 else if(x<o->v) return rk(o->ch[0],x); 113 else return r+ o->num +rk(o->ch[1],x); 114 } 115 int pre(Node* o,int x) 116 { 117 if(o==NULL) return -MAXI; 118 int d=o->cmp(x); 119 if(d<=0) return pre(o->ch[0],x); 120 else return max(o->v,pre(o->ch[1],x)); 121 } 122 int nxt(Node* o,int x) 123 { 124 if(o==NULL) return MAXI; 125 int d=o->cmp(x); 126 if(d!=0) return nxt(o->ch[1],x); 127 else return min(o->v,nxt(o->ch[0],x)); 128 } 129 int main() 130 { 131 int i,o,x; 132 scanf("%d",&n); 133 for(i=1;i<=n;i++) 134 { 135 scanf("%d%d",&o,&x); 136 if(o==1) insert(root,x); 137 else if(o==2) remove(root,x); 138 else if(o==3) printf("%d\n",rk(root,x)); 139 else if(o==4) printf("%d\n",kth(root,x)); 140 else if(o==5) printf("%d\n",pre(root,x)); 141 else printf("%d\n",nxt(root,x)); 142 } 143 return 0; 144 }
本来想写成相同的数分成多个节点放的,写了一会儿各种细节,炸了
1 #include<cstdio> 2 #include<cstdlib> 3 #include<ctime> 4 #include<algorithm> 5 using namespace std; 6 struct Node 7 { 8 Node* ch[2]; 9 int r;//优先级 10 int v;//value 11 int size;//维护子树的节点个数 12 13 int cmp(int x) const//要在当前节点的哪个子树去查找,0左1右 14 { 15 if(x==v) return -1; 16 return v<x;//x<v?0:1 17 } 18 void upd() 19 { 20 size=1; 21 if(ch[0]!=NULL) size+=ch[0]->size; 22 if(ch[1]!=NULL) size+=ch[1]->size; 23 } 24 }nodes[200100]; 25 int mem; 26 void rotate(Node* &o,int d) 27 { 28 Node* t=o->ch[d^1];o->ch[d^1]=t->ch[d];t->ch[d]=o; 29 o->upd();t->upd(); 30 o=t;//将当前节点变成旋转完后新的父节点 31 } 32 Node* getnode() 33 { 34 return &nodes[mem++]; 35 } 36 void insert(Node* &o,int x) 37 { 38 if(o==NULL) 39 { 40 o=getnode();o->ch[0]=o->ch[1]=NULL; 41 o->v=x;o->r=rand(); 42 } 43 else 44 { 45 //int d=o->cmp(x);不重复 46 int d=o->v <= x;//x < o->v?0:1 47 //按照以上左侧的插入方式,相等的会在左子树中插入 48 insert(o->ch[d],x); 49 if(o->ch[d]->r > o->r)//不是> x 50 rotate(o,d^1); 51 } 52 o->upd(); 53 } 54 void remove(Node* &o,int x) 55 { 56 int d=o->cmp(x); 57 if(d==-1) 58 { 59 if(o->ch[0]==NULL) o=o->ch[1]; 60 else if(o->ch[1]==NULL) o=o->ch[0]; 61 else 62 { 63 //int d2= o->ch[0]->r > o->ch[1]->r;//o->ch[0]->r > o->ch[1]->r ? 1:0 64 int d2=o->ch[1]->r <= o->ch[0]->r; 65 rotate(o,d2); 66 remove(o->ch[d2],x); 67 //左旋则原节点变为新节点的左子节点,右旋相反 68 } 69 } 70 else remove(o->ch[d],x); 71 if(o!=NULL) o->upd(); 72 } 73 bool find(Node* o,int x) 74 { 75 int d; 76 while(o!=NULL) 77 { 78 d=o->cmp(x); 79 if(d==-1) return 1; 80 else o=o->ch[d]; 81 } 82 return 0; 83 } 84 int kth(Node* o,int k) 85 { 86 if(o==NULL||k<=0||k > o->size) return 0; 87 int s= o->ch[0]==NULL ? 0 : o->ch[0]->size; 88 if(k==s+1) return o->v; 89 else if(k<=s) return kth(o->ch[0],k); 90 else return kth(o->ch[1],k-s-1); 91 } 92 //int rank(Node* o,int x)//不可重复 93 //{ 94 // int r= t->ch[0]==NULL ? 0 : t->ch[0]->size; 95 // if(x==o->v) return r+1; 96 // else if(x<o->v) return rank(o->ch[0],x); 97 // else return r+1+rank(o->ch[1],x); 98 //} 99 int rank(Node* o,int x)//支持重复 100 { 101 int r=t->ch[0]==NULL ? 0 : t->ch[0]->size; 102 if(x==o->v) 103 { 104 int t=rank(o->ch[ 105 } 106 } 107 int pre(Node* o,int x) 108 { 109 if(o==NULL) return -1; 110 if(x==o->v) return 111 if(x<o->v) return min(o->v,pre(o->ch[0], 112 } 113 int main() 114 { 115 srand(time(0)); 116 117 return 0; 118 }