SBT专题训练
SBT的资料很多(陈启峰的论文以及下面的blog),在这里就不再叙述:给出下面几道题目以及代码:
http://www.cnblogs.com/reflec94/archive/2011/01/22/1942095.html
BZOJ 1208 [HNOI2002]营业额统计 {Insert , pred , succ , find}
View Code
1 /* 2 3 题目: 4 最小波动值= min { | 该天以前某一天的营业额-该天的营业额 | } 5 6 分析: 7 求前驱以及后继与当前的数相减的绝对值的最小值。 8 9 */ 10 #include <cstdio> 11 #include <cstring> 12 #include <iostream> 13 #include <cstdlib> 14 15 using namespace std; 16 17 const int X = 1111111; 18 19 int root,tol,n; 20 bool use[X] = {0}; 21 22 struct node{ 23 int val,l,r,s; 24 void init(int _val){ 25 l = r = 0; 26 s = 1; 27 val = _val; 28 } 29 }sbt[X]; 30 31 void left_rotate(int &t){ 32 int k = sbt[t].r; 33 sbt[t].r = sbt[k].l; 34 sbt[k].l = t; 35 sbt[k].s = sbt[t].s; 36 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 37 t = k; 38 } 39 40 void right_rotate(int &t){ 41 int k = sbt[t].l; 42 sbt[t].l = sbt[k].r; 43 sbt[k].r = t; 44 sbt[k].s = sbt[t].s; 45 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 46 t = k; 47 } 48 49 void maintain(int &t,bool ok){ 50 if(!ok){ 51 if(sbt[sbt[sbt[t].l].l].s>sbt[sbt[t].r].s) 52 right_rotate(t); 53 else if(sbt[sbt[sbt[t].l].r].s>sbt[sbt[t].r].s){ 54 left_rotate(sbt[t].l); 55 right_rotate(t); 56 } 57 else return; 58 } 59 else{ 60 if(sbt[sbt[sbt[t].r].r].s>sbt[sbt[t].l].s) 61 left_rotate(t); 62 else if(sbt[sbt[sbt[t].r].l].s>sbt[sbt[t].l].s){ 63 right_rotate(sbt[t].r); 64 left_rotate(t); 65 } 66 else return; 67 } 68 maintain(sbt[t].l,0); 69 maintain(sbt[t].r,1); 70 maintain(t,0); 71 maintain(t,1); 72 } 73 74 void insert(int &t,int val){ 75 if(!t){ 76 t = ++tol; 77 sbt[t].init(val); 78 return; 79 } 80 sbt[t].s++; 81 if(val<sbt[t].val) 82 insert(sbt[t].l,val); 83 else 84 insert(sbt[t].r,val); 85 maintain(t,val>=sbt[t].val); 86 } 87 88 int get_pre(int t,int val){ 89 if(!t) 90 return val; 91 if(val<=sbt[t].val) 92 return get_pre(sbt[t].l,val); 93 else{ 94 int temp = get_pre(sbt[t].r,val); 95 return temp==val?sbt[t].val:temp; 96 } 97 } 98 99 int get_succ(int t,int val){ 100 if(!t) 101 return val; 102 if(val>=sbt[t].val) 103 return get_succ(sbt[t].r,val); 104 else{ 105 int temp = get_succ(sbt[t].l,val); 106 return temp==val?sbt[t].val:temp; 107 } 108 } 109 110 int main(){ 111 freopen("sum.in","r",stdin); 112 //freopen("sum.out","w",stdout); 113 root = tol = 0; 114 int ans = 0,x; 115 cin>>n>>x; 116 int qq = 1000000; 117 ans = x; 118 insert(root,x); 119 use[x+qq] = true; 120 int xx,yy; 121 for(int i=1;i<n;i++){ 122 if(scanf("%d",&x)==EOF) 123 x = 0; 124 if(use[qq+x]) 125 continue; 126 use[qq+x] = true; 127 if(!(xx = x-get_pre(root,x))) 128 xx = X; 129 if(!(yy = get_succ(root,x)-x)) 130 yy = X; 131 132 ans += min(xx,yy); 133 insert(root,x); 134 } 135 cout<<ans<<endl; 136 return 0; 137 }
BZOJ 1503 [NOI2004]郁闷的出纳员 {Insert , DeleteSmall , Select}
View Code
1 /* 2 3 题目: 4 第一行有两个非负整数n和min。n表示下面有多少条命令,min表示工资下界。 5 接下来的n行,每行表示一条命令。命令可以是以下四种之一: 6 I命令(I k): 新建一个工资档案,初始工资为k。如果某员工的初始工资低 7 于工资下界,他将立刻离开公司。 8 A命令(A k): 把每位员工的工资加上k 9 S命令(S k): 把每位员工的工资扣除k 10 F命令(F k): 查询第k多的工资 11 一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻 12 气愤地离开公司,并且再也不会回来了。问现在工资第k多的员工拿多少工资 13 14 分析: 15 像线段树的lazy标记一样,设置标记delay表示当前为止已经增加了的工资, 16 若重新来了一名新员工的话,得要把他的工资减掉delay,表示他现在的工资 17 (因为在delete操作中是SBT中的val值加上delay)。其他的基本如同SBT求 18 第K大了。 19 20 */ 21 #include <iostream> 22 #include <cstdio> 23 #include <cstring> 24 25 using namespace std; 26 27 const int X = 100005; 28 29 int root,tol; 30 31 struct node{ 32 int l,r,val,s; 33 void init(){ 34 l = r = 0; 35 s = 1; 36 } 37 }sbt[X]; 38 39 void left_rotate(int &t){ 40 int k = sbt[t].r; 41 sbt[t].r = sbt[k].l; 42 sbt[k].l = t; 43 sbt[k].s = sbt[t].s; 44 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 45 t = k; 46 } 47 48 void right_rotate(int &t){ 49 int k = sbt[t].l; 50 sbt[t].l = sbt[k].r; 51 sbt[k].r = t; 52 sbt[k].s = sbt[t].s; 53 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 54 t = k; 55 } 56 57 void maintain(int &t,bool ok){ 58 if(!ok){ 59 if(sbt[sbt[sbt[t].l].l].s>sbt[sbt[t].r].s) 60 right_rotate(t); 61 else if(sbt[sbt[sbt[t].l].r].s>sbt[sbt[t].r].s){ 62 left_rotate(sbt[t].l); 63 right_rotate(t); 64 } 65 else 66 return; 67 } 68 else{ 69 if(sbt[sbt[sbt[t].r].r].s>sbt[sbt[t].l].s) 70 left_rotate(t); 71 else if(sbt[sbt[sbt[t].r].l].s>sbt[sbt[t].l].s){ 72 right_rotate(sbt[t].r); 73 left_rotate(t); 74 } 75 else 76 return; 77 } 78 maintain(sbt[t].l,0); 79 maintain(sbt[t].r,1); 80 maintain(t,0); 81 maintain(t,1); 82 } 83 84 void insert(int &t,int val){ 85 if(!t){ 86 t = ++tol; 87 sbt[t].init(); 88 sbt[t].val = val; 89 return; 90 } 91 sbt[t].s++; 92 if(val<sbt[t].val) 93 insert(sbt[t].l,val); 94 else 95 insert(sbt[t].r,val); 96 maintain(t,val>=sbt[t].val); 97 } 98 99 int del(int &t,int val){ 100 if(!t) 101 return 0; 102 sbt[t].s--; 103 if(sbt[t].val==val||(val<sbt[t].val&&!sbt[t].l)||(val>sbt[t].val&&!sbt[t].r)){ 104 if(sbt[t].l&&sbt[t].r){ 105 int pos = del(sbt[t].l,val+1); 106 sbt[t].val = sbt[pos].val; 107 return pos; 108 } 109 else{ 110 int pos = t; 111 t = sbt[t].l+sbt[t].r; 112 return pos; 113 } 114 } 115 else 116 return del(val<sbt[t].val?sbt[t].l:sbt[t].r,val); 117 } 118 119 void Delete(int &t,int delay,int min_val){ 120 if(!t) 121 return; 122 if(sbt[t].val+delay<min_val){ 123 t = sbt[t].r; 124 Delete(t,delay,min_val); 125 } 126 else{ 127 Delete(sbt[t].l,delay,min_val); 128 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 129 } 130 } 131 132 int find_k(int &t,int k){ 133 if(k<=sbt[sbt[t].l].s) 134 return find_k(sbt[t].l,k); 135 else if(k>sbt[sbt[t].l].s+1) 136 return find_k(sbt[t].r,k-sbt[sbt[t].l].s-1); 137 else 138 return sbt[t].val; 139 } 140 141 int find_k_max(int &t,int k){ 142 if(k<=sbt[sbt[t].r].s) 143 return find_k_max(sbt[t].r,k); 144 else if(k>sbt[sbt[t].r].s+1) 145 return find_k_max(sbt[t].l,k-sbt[sbt[t].r].s-1); 146 else 147 return sbt[t].val; 148 } 149 150 int get_rank(int &t,int val){ 151 if(val<sbt[t].val) 152 return get_rank(sbt[t].l,val); 153 else if(val>sbt[t].val) 154 return get_rank(sbt[t].r,val)+sbt[sbt[t].l].s+1; 155 else 156 return sbt[sbt[t].l].s+1; 157 } 158 159 void inorder(int &t){ 160 if(!t) 161 return; 162 inorder(sbt[t].l); 163 printf("%d\n",sbt[t].val); 164 inorder(sbt[t].r); 165 } 166 167 int get_min(int &t){ 168 while(sbt[t].l) 169 t = sbt[t].l; 170 return t; 171 } 172 173 int get_max(int &t){ 174 while(sbt[t].r) 175 t = sbt[t].r; 176 return t; 177 } 178 179 int main(){ 180 freopen("sum.in","r",stdin); 181 int x; 182 int n,min_val,delay; 183 char str[5]; 184 while(cin>>n>>min_val){ 185 root = delay = tol = 0; 186 while(n--){ 187 scanf("%s%d",str,&x); 188 if(str[0]=='I'){ 189 if(x<min_val) 190 continue; 191 insert(root,x-delay); 192 } 193 else if(str[0]=='A') 194 delay += x; 195 else if(str[0]=='S'){ 196 delay -= x; 197 Delete(root,delay,min_val); 198 } 199 else 200 printf("%d\n",sbt[root].s>=x?find_k_max(root,x)+delay:-1); 201 } 202 printf("%d\n",tol-sbt[root].s); 203 } 204 return 0; 205 }
BZOJ 1588 [HNOI2004]宠物收养所 {Insert , pred , succ , Delete}
View Code
1 /* 2 3 分析: 4 SBT功能的应用:删除、前驱、后继 5 这题就是简单的元素插入删除操作,注意一下绝对值相同的时候取较小的即可, 6 还有就是每次收养所里要么都是人,要么都是宠物。 7 当树种相同的时候,直接插入SBT中,当树种不一样的时候,从SBT中找到满足条 8 件的前驱或者后继,更新答案后在SBT中删除该值即可 9 10 */ 11 #include <iostream> 12 #include <cstdio> 13 #include <cstring> 14 15 using namespace std; 16 17 const int X = 1000005; 18 const long long mod = 1000000; 19 #define debug puts("here"); 20 21 int root,tol; 22 23 struct node{ 24 int l,r,s,val; 25 void init(int _val){ 26 l = r = 0; 27 s = 1; 28 val = _val; 29 } 30 }sbt[X]; 31 32 void left_rotate(int &t){ 33 int k = sbt[t].r; 34 sbt[t].r = sbt[k].l; 35 sbt[k].l = t; 36 sbt[k].s = sbt[t].s; 37 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 38 t = k; 39 } 40 41 void right_rotate(int &t){ 42 int k = sbt[t].l; 43 sbt[t].l = sbt[k].r; 44 sbt[k].r = t; 45 sbt[k].s = sbt[t].s; 46 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 47 t = k; 48 } 49 50 void maintain(int &t,bool ok){ 51 if(!ok){ 52 if(sbt[sbt[sbt[t].l].l].s>sbt[sbt[t].r].s) 53 right_rotate(t); 54 else if(sbt[sbt[sbt[t].l].r].s>sbt[sbt[t].l].s){ 55 left_rotate(sbt[t].l); 56 right_rotate(t); 57 } 58 else return; 59 } 60 else{ 61 if(sbt[sbt[sbt[t].r].r].s>sbt[sbt[t].l].s) 62 left_rotate(t); 63 else if(sbt[sbt[sbt[t].r].l].s>sbt[sbt[t].l].s){ 64 right_rotate(sbt[t].r); 65 left_rotate(t); 66 } 67 else return; 68 } 69 maintain(sbt[t].l,0); 70 maintain(sbt[t].r,1); 71 maintain(t,0); 72 maintain(t,1); 73 } 74 75 void insert(int &t,int val){ 76 if(!t){ 77 t = ++tol; 78 sbt[t].init(val); 79 return; 80 } 81 sbt[t].s++; 82 if(val<sbt[t].val) 83 insert(sbt[t].l,val); 84 else 85 insert(sbt[t].r,val); 86 maintain(t,val>=sbt[t].val); 87 } 88 89 int del(int &t,int val){ 90 if(!t) return 0; 91 sbt[t].s--; 92 if(val==sbt[t].val||(val<sbt[t].val&&!sbt[t].l)||(val>sbt[t].val&&!sbt[t].r)){ 93 if(sbt[t].l&&sbt[t].r){ 94 int pos = del(sbt[t].l,val+1); 95 sbt[t].val = sbt[pos].val; 96 return pos; 97 } 98 else{ 99 int pos = t; 100 t = sbt[t].l+sbt[t].r; 101 return pos; 102 } 103 } 104 return del(val<sbt[t].val?sbt[t].l:sbt[t].r,val); 105 } 106 107 int get_pre(int t,int val){ 108 if(!t) return val; 109 if(val<=sbt[t].val) 110 return get_pre(sbt[t].l,val); 111 else{ 112 int temp = get_pre(sbt[t].r,val); 113 return temp==val?sbt[t].val:temp; 114 } 115 } 116 117 int get_succ(int t,int val){ 118 if(!t) return val; 119 if(val>=sbt[t].val) 120 return get_succ(sbt[t].r,val); 121 else{ 122 int temp = get_succ(sbt[t].l,val); 123 return val==temp?sbt[t].val:temp; 124 } 125 } 126 127 int main(){ 128 freopen("sum.in","r",stdin); 129 int n,x,y,pre,succ,op,val; 130 while(cin>>n){ 131 long long ans = 0; 132 root = tol = 0; 133 int sum = 0,kind = 0; 134 for(int i=0;i<n;i++){ 135 scanf("%d%d",&op,&val); 136 if(!sum||kind==op){ 137 kind = op; 138 insert(root,val); 139 sum++; 140 } 141 else{ 142 pre = get_pre(root,val); 143 succ = get_succ(root,val); 144 x = val-pre; 145 y = succ-val; 146 sum--; 147 if(!x){ 148 ans = (ans+y)%mod; 149 del(root,succ); 150 continue; 151 } 152 if(!y){ 153 ans = (ans+x)%mod; 154 del(root,pre); 155 continue; 156 } 157 if(x<=y){ 158 ans = (ans+x)%mod; 159 del(root,pre); 160 } 161 else{ 162 ans = (ans+y)%mod; 163 del(root,succ); 164 } 165 } 166 } 167 cout<<ans<<endl; 168 } 169 return 0; 170 }
poj 3481 Double Queue {Insert , DeleteMax , DeleteMin}
View Code
1 /* 2 3 题目: 4 三种操作: 5 0 The system needs to stop serving 6 1 K P Add client K to the waiting list with priority P 7 2 Serve the client with the highest priority and drop him or her from the waiting list 8 3 Serve the client with the lowest priority and drop him or her from the waiting list 9 问出队序列 10 11 分析: 12 2号操作的时候,直接搜索右子树的最右儿子的val域 13 3号操作的时候,直接搜索左子树的最左儿子的val域 14 15 */ 16 #include <iostream> 17 #include <cstdio> 18 #include <cstring> 19 20 using namespace std; 21 22 const int X = 1e6+5; 23 24 int root,tol; 25 26 struct node{ 27 int l,r,s,id,val; 28 void init(int _val,int _id){ 29 l = r = 0; 30 s = 1; 31 val = _val; 32 id = _id; 33 } 34 }sbt[X]; 35 36 void left_rotate(int &t){ 37 int k = sbt[t].r; 38 sbt[t].r = sbt[k].l; 39 sbt[k].l = t; 40 sbt[k].s = sbt[t].s; 41 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 42 t = k; 43 } 44 45 void right_rotate(int &t){ 46 int k = sbt[t].l; 47 sbt[t].l = sbt[k].r; 48 sbt[k].r = t; 49 sbt[k].s = sbt[t].s; 50 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 51 t = k; 52 } 53 54 void maintain(int &t,bool ok){ 55 if(!ok){ 56 if(sbt[sbt[sbt[t].l].l].s>sbt[sbt[t].r].s) 57 right_rotate(t); 58 else if(sbt[sbt[sbt[t].l].r].s>sbt[sbt[t].r].s){ 59 left_rotate(sbt[t].l); 60 right_rotate(t); 61 } 62 else return; 63 } 64 else{ 65 if(sbt[sbt[sbt[t].r].r].s>sbt[sbt[t].l].s) 66 left_rotate(t); 67 else if(sbt[sbt[sbt[t].r].l].s>sbt[sbt[t].l].s){ 68 right_rotate(sbt[t].r); 69 left_rotate(t); 70 } 71 else return; 72 } 73 maintain(sbt[t].l,0); 74 maintain(sbt[t].r,1); 75 maintain(t,0); 76 maintain(t,1); 77 } 78 79 void insert(int &t,int val,int id){ 80 if(!t){ 81 t = ++tol; 82 sbt[t].init(val,id); 83 return; 84 } 85 sbt[t].s++; 86 if(val<sbt[t].val) 87 insert(sbt[t].l,val,id); 88 else 89 insert(sbt[t].r,val,id); 90 maintain(t,val>=sbt[t].val); 91 } 92 93 int del(int &t,int val){ 94 if(!t) return 0; 95 sbt[t].s--; 96 if(val==sbt[t].val||(val<sbt[t].val&&!sbt[t].l)||(val>sbt[t].val&&!sbt[t].r)){ 97 if(sbt[t].l&&sbt[t].r){ 98 int pos = del(sbt[t].l,val+1); 99 sbt[t].val = sbt[pos].val; 100 return pos; 101 } 102 else{ 103 int pos = t; 104 t = sbt[t].l+sbt[t].r; 105 return pos; 106 } 107 } 108 else 109 return del(val<sbt[t].val?sbt[t].l:sbt[t].r,val); 110 } 111 112 int _val; 113 114 int get_min(int t){ 115 while(sbt[t].l) 116 t = sbt[t].l; 117 _val = sbt[t].val; 118 return sbt[t].id; 119 } 120 121 int get_max(int t){ 122 while(sbt[t].r) 123 t = sbt[t].r; 124 _val = sbt[t].val; 125 return sbt[t].id; 126 } 127 128 int main() 129 { 130 freopen("aum.in","r",stdin); 131 int op,val,id,temp; 132 root = tol = 0; 133 while(scanf("%d",&op),op){ 134 if(op==1){ 135 scanf("%d%d",&id,&val); 136 insert(root,val,id); 137 } 138 else if(op==2){ 139 temp = get_max(root); 140 printf("%d\n",temp); 141 del(root,_val); 142 } 143 else{ 144 temp = get_min(root); 145 printf("%d\n",temp); 146 del(root,_val); 147 } 148 } 149 return 0; 150 }
poj 2892 Tunnel Warfare
View Code
1 /* 2 3 题目: 4 现有n座城堡在一直线上,除了两端之外,其余的都各自与相邻的城堡有道路, 5 现在有三种操作,摧毁城堡,修复城堡,询问城堡x与他相连的城堡数目(包括 6 自己)。 7 8 分析: 9 SBT,每当摧毁城堡的时候插入一个节点,当询问的时候,查找比栈顶元素小的 10 以及大的位置,两者相减再减一。 11 12 */ 13 #include <cstdio> 14 #include <cstring> 15 #include <iostream> 16 17 using namespace std; 18 19 const int X = 200005; 20 #define debug puts("here"); 21 22 int n,m; 23 int s[X],top; 24 int use[X]; 25 int root,tol; 26 27 struct node{ 28 int l,r,val,s; 29 void init(){ 30 l = r = 0; 31 s = 1; 32 } 33 }sbt[X]; 34 35 void left_rotate(int &t){ 36 int k = sbt[t].r; 37 sbt[t].r = sbt[k].l; 38 sbt[k].l = t; 39 sbt[k].s = sbt[t].s; 40 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 41 t = k; 42 } 43 44 void right_rotate(int &t){ 45 int k = sbt[t].l; 46 sbt[t].l = sbt[k].r; 47 sbt[k].r = t; 48 sbt[k].s = sbt[t].s; 49 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 50 t = k; 51 } 52 53 void maintain(int &t,bool ok){ 54 if(!ok){ 55 if(sbt[sbt[sbt[t].l].l].s>sbt[sbt[t].r].s) 56 right_rotate(t); 57 else if(sbt[sbt[sbt[t].l].r].s>sbt[sbt[t].r].s){ 58 left_rotate(sbt[t].l); 59 right_rotate(t); 60 } 61 else 62 return; 63 } 64 else{ 65 if(sbt[sbt[sbt[t].r].r].s>sbt[sbt[t].l].s) 66 left_rotate(t); 67 else if(sbt[sbt[sbt[t].r].l].s>sbt[sbt[t].l].s){ 68 right_rotate(sbt[t].r); 69 left_rotate(t); 70 } 71 else 72 return; 73 } 74 maintain(sbt[t].l,0); 75 maintain(sbt[t].r,1); 76 maintain(t,0); 77 maintain(t,1); 78 } 79 80 void insert(int &t,int val){ 81 if(!t){ 82 t = ++tol; 83 sbt[t].init(); 84 sbt[t].val = val; 85 } 86 else{ 87 sbt[t].s++; 88 if(val<sbt[t].val) 89 insert(sbt[t].l,val); 90 else 91 insert(sbt[t].r,val); 92 maintain(t,val>=sbt[t].val); 93 } 94 } 95 96 int del(int &t,int val){ 97 if(!t) 98 return 0; 99 sbt[t].s--; 100 if(val==sbt[t].val||(val<sbt[t].val&&!sbt[t].l)||(val>sbt[t].val&&!sbt[t].r)){ 101 if(sbt[t].l&&sbt[t].r){ 102 int pos = del(sbt[t].l,val+1); 103 sbt[t].val = sbt[pos].val; 104 return pos; 105 } 106 else{ 107 int pos = t; 108 t = sbt[t].l+sbt[t].r; 109 return pos; 110 } 111 } 112 else 113 return del(val<sbt[t].val?sbt[t].l:sbt[t].r,val); 114 } 115 116 int less_than(int t,int val){ 117 if(!t) 118 return 0; 119 if(val<sbt[t].val) 120 return less_than(sbt[t].l,val); 121 else 122 return max(sbt[t].val,less_than(sbt[t].r,val)); 123 } 124 125 int greater_than(int t,int val){ 126 if(!t) 127 return n+1; 128 if(val>sbt[t].val) 129 return greater_than(sbt[t].r,val); 130 else 131 return min(sbt[t].val,greater_than(sbt[t].l,val)); 132 } 133 134 int main(){ 135 freopen("sum.in","r",stdin); 136 char str[5]; 137 int x; 138 while(cin>>n>>m){ 139 for(int i=0;i<=X;i++) 140 sbt[i].init(); 141 memset(use,0,sizeof(use)); 142 top = 0; 143 root = 0; 144 tol = 0; 145 while(m--){ 146 scanf("%s",str); 147 if(str[0]=='D'){ 148 scanf("%d",&x); 149 use[x]++; 150 s[++top] = x; 151 insert(root,x); 152 } 153 else if(str[0]=='R'){ 154 if(top>0){ 155 del(root,s[top]); 156 use[s[top--]]--; 157 } 158 } 159 else{ 160 scanf("%d",&x); 161 if(use[x]) 162 puts("0"); 163 else{ 164 int r = greater_than(root,x); 165 int l = less_than(root,x); 166 //cout<<r<<" "<<l<<" "; 167 printf("%d\n",r-l-1); 168 } 169 } 170 } 171 } 172 return 0; 173 }
解决约瑟夫环问题:
ural 1521 War Games 2
View Code
1 /* 2 3 ural 1521 4 http://ac.jobdu.com/problem.php?pid=1188 5 题目1188:约瑟夫环 6 题目描述: 7 N个人围成一圈顺序编号,从1号开始按1、2、3......顺序报数,报p者退出圈外,其余的人再从1、2、3开始报数,报p的人再退出圈外,以此类推。 8 请按退出顺序输出每个退出人的原序号。 9 10 输入: 11 包括一个整数N(1<=N<=3000)及一个整数p。 12 13 输出: 14 测试数据可能有多组,对于每一组数据, 15 按退出顺序输出每个退出人的原序号。 16 17 样例输入: 18 7 3 19 样例输出: 20 3 6 2 7 5 1 4 21 22 */ 23 24 /* 25 26 分析: 27 先把所有人插入到SBT中,然后出去的时候,把他从SBT中删除,而找到要删除的 28 元素为pos = (pre+k-1)%n+1,n每出去一个人减一,而pre从0开始,若已经有人 29 出队,则置为上一个人出队的位置减一,然后就是找到第pos小即可 30 31 */ 32 33 #include <iostream> 34 #include <cstdio> 35 #include <cstring> 36 37 using namespace std; 38 39 const int X = 100005; 40 41 int root,tol,n,m; 42 43 struct node{ 44 int val,l,r,s; 45 void init(int _val){ 46 l = r = 0; 47 s = 1; 48 val = _val; 49 } 50 }sbt[X]; 51 52 void left_rotate(int &t){ 53 int k = sbt[t].r; 54 sbt[t].r = sbt[k].l; 55 sbt[k].l = t; 56 sbt[k].s = sbt[t].s; 57 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 58 t = k; 59 } 60 61 void right_rotate(int &t){ 62 int k = sbt[t].l; 63 sbt[t].l = sbt[k].r; 64 sbt[k].r = t; 65 sbt[k].s = sbt[t].s; 66 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 67 t = k; 68 } 69 70 void maintain(int &t,bool ok){ 71 if(!ok){ 72 if(sbt[sbt[sbt[t].l].l].s>sbt[sbt[t].r].s) 73 right_rotate(t); 74 else if(sbt[sbt[sbt[t].l].r].s>sbt[sbt[t].r].s){ 75 left_rotate(sbt[t].l); 76 right_rotate(t); 77 } 78 else return; 79 } 80 else{ 81 if(sbt[sbt[sbt[t].r].r].s>sbt[sbt[t].l].s) 82 left_rotate(t); 83 else if(sbt[sbt[sbt[t].r].l].s>sbt[sbt[t].l].s){ 84 right_rotate(sbt[t].r); 85 left_rotate(t); 86 } 87 else return; 88 } 89 maintain(sbt[t].l,0); 90 maintain(sbt[t].r,1); 91 maintain(t,0); 92 maintain(t,1); 93 } 94 95 void insert(int &t,int val){ 96 if(!t){ 97 t = ++tol; 98 sbt[t].init(val); 99 return; 100 } 101 sbt[t].s++; 102 if(val<sbt[t].val) 103 insert(sbt[t].l,val); 104 else 105 insert(sbt[t].r,val); 106 maintain(t,val>=sbt[t].val); 107 } 108 109 int del(int &t,int val){ 110 if(!t) return 0; 111 sbt[t].s--; 112 if(val==sbt[t].val||(val<sbt[t].val&&!sbt[t].l)||(val>sbt[t].val&&!sbt[t].r)){ 113 if(sbt[t].l&&sbt[t].r){ 114 int pos = del(sbt[t].l,val+1); 115 sbt[t].val = sbt[pos].val; 116 return pos; 117 } 118 else{ 119 int pos = t; 120 t = sbt[t].l+sbt[t].r; 121 return pos; 122 } 123 } 124 else 125 return del(val<sbt[t].val?sbt[t].l:sbt[t].r,val); 126 } 127 128 int find_k_min(int &t,int k){ //找到第k小 129 if(k<=sbt[sbt[t].l].s) 130 return find_k_min(sbt[t].l,k); 131 else if(k>sbt[sbt[t].l].s+1) 132 return find_k_min(sbt[t].r,k-sbt[sbt[t].l].s-1); 133 else 134 return sbt[t].val; 135 } 136 137 int main() 138 { 139 freopen("sum.in","r",stdin); 140 freopen("sum.out","w",stdout); 141 while(cin>>n>>m){ 142 int pos = 0,temp,val; 143 root = tol = 0; 144 for(int i=1;i<=n;i++) 145 insert(root,i); 146 while(n){ 147 temp = (pos+m-1)%n+1; 148 pos = temp-1; 149 val = find_k_min(root,temp); 150 del(root,val); 151 printf("%d",val); 152 if(n>1) 153 putchar(' '); 154 n--; 155 } 156 puts(""); 157 } 158 return 0; 159 }
poj 3750 小孩报数问题(跟上面一题基本一样)
View Code
1 /* 2 3 题目: 4 约瑟夫环 5 6 */ 7 #include <iostream> 8 #include <cstdio> 9 #include <cstring> 10 11 using namespace std; 12 13 const int X = 100; 14 15 char str[X][20]; 16 int n; 17 int root,tol; 18 19 struct node{ 20 int l,r,val,s; 21 void init(){ 22 l = r = 0; 23 s = 1; 24 } 25 }sbt[X]; 26 27 void left_rotate(int &t){ 28 int k = sbt[t].r; 29 sbt[t].r = sbt[k].l; 30 sbt[k].l = t; 31 sbt[k].s = sbt[t].s; 32 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 33 t = k; 34 } 35 36 void right_rotate(int &t){ 37 int k = sbt[t].l; 38 sbt[t].l = sbt[k].r; 39 sbt[k].r = t; 40 sbt[k].s = sbt[t].s; 41 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 42 t = k; 43 } 44 45 void maintain(int &t,bool ok){ 46 if(!ok){ 47 if(sbt[sbt[sbt[t].l].l].s>sbt[sbt[t].r].s) 48 right_rotate(t); 49 else if(sbt[sbt[sbt[t].l].r].s>sbt[sbt[t].r].s){ 50 left_rotate(sbt[t].l); 51 right_rotate(t); 52 } 53 else 54 return; 55 } 56 else{ 57 if(sbt[sbt[sbt[t].r].r].s>sbt[sbt[t].l].s) 58 left_rotate(t); 59 else if(sbt[sbt[sbt[t].r].l].s>sbt[sbt[t].r].s){ 60 right_rotate(sbt[t].r); 61 left_rotate(t); 62 } 63 else 64 return; 65 } 66 maintain(sbt[t].l,0); 67 maintain(sbt[t].r,1); 68 maintain(t,0); 69 maintain(t,1); 70 } 71 72 void insert(int &t,int val){ 73 if(!t){ 74 t = ++tol; 75 sbt[t].init(); 76 sbt[t].val = val; 77 return; 78 } 79 sbt[t].s++; 80 if(val<sbt[t].val) 81 insert(sbt[t].l,val); 82 else 83 insert(sbt[t].r,val); 84 maintain(t,val>=sbt[t].val); 85 } 86 87 int del(int &t,int val){ 88 if(!t) 89 return 0; 90 sbt[t].s--; 91 if(sbt[t].val==val||(val<sbt[t].val&&!sbt[t].l)||(val>sbt[t].val&&!sbt[t].r)){ 92 if(sbt[t].l&&sbt[t].r){ 93 int pos = del(sbt[t].l,val+1); 94 sbt[t].val = sbt[pos].val; 95 return pos; 96 } 97 else{ 98 int pos = t; 99 t = sbt[t].l+sbt[t].r; 100 return pos; 101 } 102 } 103 else 104 return del(val<sbt[t].val?sbt[t].l:sbt[t].r,val); 105 } 106 107 int find_k_min(int &t,int k){ //找到第k小 108 if(k<=sbt[sbt[t].l].s) 109 return find_k_min(sbt[t].l,k); 110 else if(k>sbt[sbt[t].l].s+1) 111 return find_k_min(sbt[t].r,k-sbt[sbt[t].l].s-1); 112 else 113 return sbt[t].val; 114 } 115 116 int main(){ 117 freopen("sum.in","r",stdin); 118 int x,y; 119 while(cin>>n){ 120 tol = root = 0; 121 for(int i=1;i<=n;i++){ 122 scanf("%s",str[i]); 123 insert(root,i); 124 } 125 scanf("%d,%d",&x,&y); 126 x--; 127 while(n){ 128 int temp = (x+y-1)%n+1; 129 x = temp-1; 130 temp = find_k_min(root,temp); 131 printf("%s\n",str[temp]); 132 del(root,temp); 133 n--; 134 } 135 } 136 return 0; 137 }
poj 3517 And Then There Was One
View Code
1 /* 2 3 题目: 4 约瑟夫环问题,问最后只剩下的元素 5 6 */ 7 #include <cstdio> 8 #include <cstring> 9 #include <iostream> 10 11 using namespace std; 12 13 const int X = 100005; 14 #define debug puts("here"); 15 16 int tol,root; 17 18 struct node{ 19 int l,r,val,s; 20 void init(int _val){ 21 l = r = 0; 22 s = 1; 23 val = _val; 24 } 25 }sbt[X]; 26 27 void left_rotate(int &t){ 28 int k = sbt[t].r; 29 sbt[t].r = sbt[k].l; 30 sbt[k].l = t; 31 sbt[k].s = sbt[t].s; 32 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 33 t = k; 34 } 35 36 void right_rotate(int &t){ 37 int k = sbt[t].l; 38 sbt[t].l = sbt[k].r; 39 sbt[k].r = t; 40 sbt[k].s = sbt[t].s; 41 sbt[t].s = sbt[sbt[t].l].s+sbt[sbt[t].r].s+1; 42 t = k; 43 } 44 45 void maintain(int &t,bool ok){ 46 if(!ok){ 47 if(sbt[sbt[sbt[t].l].l].s>sbt[sbt[t].r].s) 48 right_rotate(t); 49 else if(sbt[sbt[sbt[t].l].r].s>sbt[sbt[t].r].s){ 50 left_rotate(sbt[t].l); 51 right_rotate(t); 52 } 53 else return; 54 } 55 else{ 56 if(sbt[sbt[sbt[t].r].r].s>sbt[sbt[t].l].s) 57 left_rotate(t); 58 else if(sbt[sbt[sbt[t].r].l].s>sbt[sbt[t].l].s){ 59 right_rotate(sbt[t].r); 60 left_rotate(t); 61 } 62 else return; 63 } 64 maintain(sbt[t].l,0); 65 maintain(sbt[t].r,1); 66 maintain(t,0); 67 maintain(t,1); 68 } 69 70 void insert(int &t,int val){ 71 if(!t){ 72 t = ++tol; 73 sbt[t].init(val); 74 return; 75 } 76 sbt[t].s++; 77 if(val<sbt[t].val) 78 insert(sbt[t].l,val); 79 else 80 insert(sbt[t].r,val); 81 maintain(t,val>=sbt[t].val); 82 } 83 84 int del(int &t,int val){ 85 if(!t) return 0; 86 sbt[t].s--; 87 if(sbt[t].val==val||(val<sbt[t].val&&!sbt[t].l)||(val>sbt[t].val&&!sbt[t].r)){ 88 if(sbt[t].l&&sbt[t].r){ 89 int pos = del(sbt[t].l,val+1); 90 sbt[t].val = sbt[pos].val; 91 return pos; 92 } 93 else{ 94 int pos = t; 95 t = sbt[t].l+sbt[t].r; 96 return pos; 97 } 98 } 99 else 100 return del(val<sbt[t].val?sbt[t].l:sbt[t].r,val); 101 } 102 103 int find_k_min(int &t,int k){ 104 if(k<=sbt[sbt[t].l].s) 105 return find_k_min(sbt[t].l,k); 106 else if(k>sbt[sbt[t].l].s+1) 107 return find_k_min(sbt[t].r,k-sbt[sbt[t].l].s-1); 108 return sbt[t].val; 109 } 110 111 int find_k_max(int &t,int k){ 112 if(k<sbt[sbt[t].r].s) 113 return find_k_max(sbt[t].r,k); 114 else if(k>sbt[sbt[t].r].s+1) 115 return find_k_max(sbt[t].l,k-sbt[sbt[t].r].s-1); 116 return sbt[t].val; 117 } 118 119 int get_pre(int &t,int val){ 120 if(!t) return 0; 121 if(val<sbt[t].val) 122 return get_pre(sbt[t].l,val); 123 else 124 return max(sbt[t].val,get_pre(sbt[t].r,val)); 125 } 126 127 int get_next(int &t,int val){ 128 if(!t) return 0; 129 if(val>sbt[t].val) 130 return get_next(sbt[t].r,val); 131 else 132 return min(sbt[t].val,get_next(sbt[t].l,val)); 133 } 134 135 int get_rank(int &t,int val){ 136 if(val<sbt[t].val) 137 return get_rank(sbt[t].l,val); 138 else if(val>sbt[t].val) 139 return get_rank(sbt[t].r,val)+sbt[sbt[t].l].s+1; 140 else 141 return sbt[sbt[t].l].s+1; 142 } 143 144 int main(){ 145 freopen("sum.in","r",stdin); 146 int n,k,s; 147 while(cin>>n>>k>>s,n||k||s){ 148 if(n==1){ 149 puts("1"); 150 continue; 151 } 152 root = tol = 0; 153 for(int i=1;i<=n;i++) 154 insert(root,i); 155 int pos = s+n-k; 156 while(n){ 157 int temp = (pos+k-1)%n+1; 158 pos = temp-1; 159 temp = find_k_min(root,temp); 160 del(root,temp); 161 if(n==2){ 162 printf("%d\n",find_k_min(root,1)); 163 break; 164 } 165 n--; 166 } 167 } 168 return 0; 169 }