Splay

AC tyvj1728 普通平衡树

  1. 1 #include <cstdio>
  2. 2 #include <iostream>
  3. 3 #include <fstream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <cmath>
  8. 8 #include <algorithm>
  9. 9
  10. 10 typedef long long int ll;
  11. 11 typedef double db;
  12. 12
  13. 13 using namespace std;
  14. 14
  15. 15 struct SplayTree
  16. 16 {
  17. 17 struct node
  18. 18 {
  19. 19 int v;
  20. 20 int tot;
  21. 21 node*s[2];
  22. 22 node*f;
  23. 23
  24. 24 void update()
  25. 25 {
  26. 26 tot=s[0]->tot + s[1]->tot +1;
  27. 27 }
  28. 28 };
  29. 29 node*pool;
  30. 30 node*nt;
  31. 31 node*nil;
  32. 32 node*newnode(node*f,int v)
  33. 33 {
  34. 34 nt->v=v;
  35. 35 nt->tot=1;
  36. 36 nt->s[0]=nt->s[1]=nil;
  37. 37 nt->f=f;
  38. 38 return nt++;
  39. 39 }
  40. 40
  41. 41 node*root;
  42. 42
  43. 43 SplayTree(int size)
  44. 44 {
  45. 45 pool=new node[size+1];
  46. 46 nt=pool;
  47. 47 nil=newnode(NULL,-1);
  48. 48 nil->tot=0;
  49. 49 nil->f=nil->s[0]=nil->s[1]=nil;
  50. 50 root=nil;
  51. 51 }
  52. 52
  53. 53 //===============================================
  54. 54
  55. 55 void update(node*x)
  56. 56 {
  57. 57 x->tot= x->s[0]->tot + x->s[1]->tot +1;
  58. 58 }
  59. 59
  60. 60 void rot(node*x)
  61. 61 {
  62. 62 if(x==nil) return ;
  63. 63
  64. 64 node*y=x->f;
  65. 65 int k=(x==y->s[0]);
  66. 66
  67. 67 y->s[k^1]=x->s[k];
  68. 68 if(x->s[k]!=nil) x->s[k]->f=y;
  69. 69
  70. 70 x->f=y->f;
  71. 71 if(y==y->f->s[0]) y->f->s[0]=x;
  72. 72 else if(y==y->f->s[1]) y->f->s[1]=x;
  73. 73
  74. 74 y->f=x;
  75. 75 x->s[k]=y;
  76. 76
  77. 77 y->update();
  78. 78 }
  79. 79
  80. 80 void splay(node*x) { splay(x,nil); }
  81. 81 void splay(node*x,node*t)
  82. 82 {
  83. 83 if(x==nil) return ;
  84. 84 while(x->f!=t)
  85. 85 {
  86. 86 node*y=x->f;
  87. 87 if(y->f!=t)
  88. 88 if((x==y->s[0])^(y==y->f->s[0]))
  89. 89 rot(x); else rot(y);
  90. 90 rot(x);
  91. 91 }
  92. 92 x->update();
  93. 93
  94. 94 if(t==nil) root=x;
  95. 95 }
  96. 96
  97. 97 //=============================================
  98. 98
  99. 99 void Insert(int v)
  100. 100 {
  101. 101 if(root==nil)
  102. 102 {
  103. 103 root=newnode(nil,v);
  104. 104 return ;
  105. 105 }
  106. 106
  107. 107 node*x=root;
  108. 108 node*y=x;
  109. 109 while(x!=nil)
  110. 110 {
  111. 111 y=x;
  112. 112 if(v<x->v) x=x->s[0];
  113. 113 else x=x->s[1];
  114. 114 }
  115. 115
  116. 116 int k=!(v<y->v);
  117. 117 y->s[k]=newnode(y,v);
  118. 118 splay(y->s[k]);
  119. 119 }
  120. 120
  121. 121
  122. 122 node*Find(int v)
  123. 123 {
  124. 124 node*x=root;
  125. 125 node*y=x;
  126. 126 node*r=nil;
  127. 127 while(x!=nil)
  128. 128 {
  129. 129 y=x;
  130. 130 if(x->v==v) r=x;
  131. 131 if(v<=x->v) x=x->s[0];
  132. 132 else x=x->s[1];
  133. 133 }
  134. 134 splay(y);
  135. 135 return r;
  136. 136 }
  137. 137
  138. 138 node* FindRank(int k)
  139. 139 {
  140. 140 node*x=root;
  141. 141 node*y=x;
  142. 142 while(x!=nil)
  143. 143 {
  144. 144 y=x;
  145. 145 if(k==x->s[0]->tot+1) break;
  146. 146
  147. 147 if(k<x->s[0]->tot+1)
  148. 148 x=x->s[0];
  149. 149 else
  150. 150 {
  151. 151 k-=x->s[0]->tot+1;
  152. 152 x=x->s[1];
  153. 153 }
  154. 154 }
  155. 155 splay(y);
  156. 156 return x;
  157. 157 }
  158. 158
  159. 159 int GetRank(node*x)
  160. 160 {
  161. 161 splay(x);
  162. 162 return x->s[0]->tot+1;
  163. 163 }
  164. 164
  165. 165 int GetRevRank(node*x)
  166. 166 {
  167. 167 splay(x);
  168. 168 return x->s[1]->tot+1;
  169. 169 }
  170. 170
  171. 171 node*Delete(node*x)
  172. 172 {
  173. 173 int k=GetRank(x);
  174. 174 node*L=FindRank(k-1);
  175. 175 node*R=FindRank(k+1);
  176. 176
  177. 177 splay(L);
  178. 178 splay(R,L);
  179. 179
  180. 180 if(L==nil && R==nil) root=nil;
  181. 181 else if(R==nil) L->s[1]=nil;
  182. 182 else R->s[0]=nil;
  183. 183
  184. 184 if(R!=nil) update(R);
  185. 185 if(L!=nil) update(L);
  186. 186
  187. 187 return x;
  188. 188 }
  189. 189
  190. 190 node*prefix(int v)
  191. 191 {
  192. 192 node*x=root;
  193. 193 node*y=x;
  194. 194 node*r=nil;
  195. 195 while(x!=nil)
  196. 196 {
  197. 197 y=x;
  198. 198 if(x->v<v) r=x;
  199. 199 if(v<=x->v) x=x->s[0];
  200. 200 else x=x->s[1];
  201. 201 }
  202. 202 splay(y);
  203. 203 return r;
  204. 204 }
  205. 205
  206. 206 node*suffix(int v)
  207. 207 {
  208. 208 node*x=root;
  209. 209 node*y=x;
  210. 210 node*r=nil;
  211. 211 while(x!=nil)
  212. 212 {
  213. 213 y=x;
  214. 214 if(x->v>v) r=x;
  215. 215 if(v<x->v) x=x->s[0];
  216. 216 else x=x->s[1];
  217. 217 }
  218. 218 splay(y);
  219. 219 return r;
  220. 220 }
  221. 221
  222. 222
  223. 223
  224. 224
  225. 225 //===========================================
  226. 226 void output() { output(root); printf("%s\n",root==nil ? "empty tree!" : ""); }
  227. 227 void output(node*x)
  228. 228 {
  229. 229 if(x==nil)return ;
  230. 230 output(x->s[0]);
  231. 231 printf("%d ",x->v);
  232. 232 output(x->s[1]);
  233. 233 }
  234. 234
  235. 235 void test() { test(root); printf("%s\n",root==nil ? "empty tree!" : ""); }
  236. 236 void test(node*x)
  237. 237 {
  238. 238 if(x==nil)return ;
  239. 239 test(x->s[0]);
  240. 240 printf("%p [ v:%d f:%p L:%p R:%p tot:%d ] \n",x,x->v,x->f,x->s[0],x->s[1],x->tot);
  241. 241 test(x->s[1]);
  242. 242 }
  243. 243
  244. 244 };
  245. 245
  246. 246
  247. 247 int n;
  248. 248
  249. 249 int main()
  250. 250 {
  251. 251 scanf("%d",&n);
  252. 252 SplayTree st(n);
  253. 253
  254. 254 for(int i=0;i<n;i++)
  255. 255 {
  256. 256 int c;
  257. 257 scanf("%d",&c);
  258. 258 switch(c)
  259. 259 {
  260. 260 case 1: //Insert
  261. 261 scanf("%d",&c);
  262. 262 st.Insert(c);
  263. 263 break;
  264. 264 case 2: //Delete
  265. 265 scanf("%d",&c);
  266. 266 st.Delete(st.Find(c));
  267. 267 break;
  268. 268 case 3: //Rank
  269. 269 scanf("%d",&c);
  270. 270 printf("%d\n",st.GetRank(st.Find(c)));
  271. 271 break;
  272. 272 case 4: //FindRank
  273. 273 scanf("%d",&c);
  274. 274 printf("%d\n",st.FindRank(c)->v);
  275. 275 break;
  276. 276 case 5: //prefix
  277. 277 scanf("%d",&c);
  278. 278 printf("%d\n",st.prefix(c)->v);
  279. 279 break;
  280. 280 case 6: //suffix
  281. 281 scanf("%d",&c);
  282. 282 printf("%d\n",st.suffix(c)->v);
  283. 283 break;
  284. 284 case 7: //test
  285. 285 st.test();
  286. 286 break;
  287. 287 default: break;
  288. 288 }
  289. 289 }
  290. 290
  291. 291 return 0;
  292. 292 }

View Code

 

2015年2月19日更新:

我现在才发现我写的双旋一直都是错的!!!!!

记住如果是折线就两次rot(x),直线才是先y后x! if((x==y->s[0])^(y==y->f->s[0])) rot(x); else rot(y);

要点1.别忘了有事没事splay一下保证复杂度…..

要点2.各种if的顺序别搞混了!有些if是不能合并的.

要点3.记住splay前的特判.如果要单独使用rotate就给rotate也加特判.

要点4.不要有事没事就更改某些子树的位置!比如在delete的时候,提x作根,然后找到右子树最左边的节点后,合并左右两颗子树,这是会超时的!

 

AC BZOJ 2733

 

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 #include <bitset>
  18. 18
  19. 19 typedef unsigned int uint;
  20. 20 typedef long long int ll;
  21. 21 typedef unsigned long long int ull;
  22. 22 typedef double db;
  23. 23
  24. 24 using namespace std;
  25. 25
  26. 26 inline int getint()
  27. 27 {
  28. 28 int res=0;
  29. 29 char c=getchar();
  30. 30 bool mi=false;
  31. 31 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  32. 32 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  33. 33 return mi ? -res : res;
  34. 34 }
  35. 35 inline ll getll()
  36. 36 {
  37. 37 ll res=0;
  38. 38 char c=getchar();
  39. 39 bool mi=false;
  40. 40 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  41. 41 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  42. 42 return mi ? -res : res;
  43. 43 }
  44. 44
  45. 45 //==============================================================================
  46. 46 //==============================================================================
  47. 47 //==============================================================================
  48. 48 //==============================================================================
  49. 49
  50. 50 struct node*nil;
  51. 51 struct node
  52. 52 {
  53. 53 int v;
  54. 54 int tot;
  55. 55 node*s[2],*f;
  56. 56 int code;
  57. 57 void update(){ tot = s[0]->tot + s[1]->tot +1; }
  58. 58
  59. 59 };
  60. 60 node*nt;
  61. 61 int ncnt=10000;
  62. 62 node*newnode(node*f,int v,int c)
  63. 63 {
  64. 64 if(ncnt==10000) { ncnt=0; nt=new node[10000]; }
  65. 65 nt->f=f;
  66. 66 nt->s[0]=nt->s[1]=nil;
  67. 67 nt->tot=1;
  68. 68 nt->v=v;
  69. 69 nt->code=c;
  70. 70 ncnt++;
  71. 71 return nt++;
  72. 72 }
  73. 73
  74. 74 struct SplayTree
  75. 75 {
  76. 76 node*root;
  77. 77
  78. 78 SplayTree(){ root=nil; }
  79. 79
  80. 80 void rot(node*x)
  81. 81 {
  82. 82 node*y=x->f;
  83. 83 if(y==nil) return ;
  84. 84 int k=(x==y->s[0]);
  85. 85
  86. 86 y->s[!k]=x->s[k];
  87. 87 if(x->s[k]!=nil) x->s[k]->f=y;
  88. 88
  89. 89 x->f=y->f;
  90. 90 if(y==y->f->s[0]) y->f->s[0]=x;
  91. 91 else if(y==y->f->s[1]) y->f->s[1]=x;
  92. 92
  93. 93 y->f=x;
  94. 94 x->s[k]=y;
  95. 95
  96. 96 y->update();
  97. 97 }
  98. 98
  99. 99 void splay(node*x,node*t=nil)
  100. 100 {
  101. 101 while(x->f!=t)
  102. 102 {
  103. 103 node*y=x->f;
  104. 104 if(y->f!=t)
  105. 105 if((x==y->s[0])^(y==y->f->s[0]))
  106. 106 rot(x); else rot(y);
  107. 107 rot(x);
  108. 108 }
  109. 109 x->update();
  110. 110 if(t==nil) root=x;
  111. 111 }
  112. 112
  113. 113 void Insert(int v,int c)
  114. 114 { root=newnode(nil,v,c); }
  115. 115
  116. 116 void Insert(node*t)
  117. 117 {
  118. 118 if(root==nil)
  119. 119 { root=t; t->s[0]=t->s[1]=t->f=nil; t->tot=1; return ; }
  120. 120
  121. 121 node*x=root;
  122. 122 node*y=nil;
  123. 123 while(x!=nil)
  124. 124 y=x,x=x->s[t->v>=x->v];
  125. 125
  126. 126 int k=(t->v>=y->v);
  127. 127
  128. 128 t->s[0]=t->s[1]=nil; t->tot=1;
  129. 129 y->s[k]=t; t->f=y;
  130. 130
  131. 131 splay(t);
  132. 132 }
  133. 133
  134. 134 node*FindRank(int k)
  135. 135 {
  136. 136 if(k>root->tot || k<=0) return nil;
  137. 137 node*x=root;
  138. 138 node*y=nil;
  139. 139 while(x!=nil)
  140. 140 {
  141. 141 y=x;
  142. 142 if(k==x->s[0]->tot+1) break;
  143. 143 if(k>x->s[0]->tot+1)
  144. 144 {
  145. 145 k-=x->s[0]->tot+1;
  146. 146 x=x->s[1];
  147. 147 }
  148. 148 else
  149. 149 x=x->s[0];
  150. 150 }
  151. 151 splay(y);
  152. 152 return y;
  153. 153 }
  154. 154 };
  155. 155
  156. 156 node*ary[105000]; int ac,ah;
  157. 157 void Merge(SplayTree*&A,SplayTree*&B)
  158. 158 {
  159. 159 if(A->root==B->root) return ;
  160. 160 if(A->root->tot>B->root->tot) swap(A,B);
  161. 161 //descrete nodes of A and insert to B.
  162. 162 ah=ac=0;
  163. 163 ary[ac++]=A->root;
  164. 164 while(ah!=ac)
  165. 165 {
  166. 166 node*x=ary[ah];
  167. 167 if(x->s[0]!=nil) ary[ac++]=x->s[0];
  168. 168 if(x->s[1]!=nil) ary[ac++]=x->s[1];
  169. 169 B->Insert(x);
  170. 170 ah++;
  171. 171 }
  172. 172 A=B;
  173. 173 }
  174. 174
  175. 175 SplayTree**T;
  176. 176
  177. 177 int n,m,q;
  178. 178
  179. 179 int main()
  180. 180 {
  181. 181 nil=new node;
  182. 182 nil->f=nil->s[0]=nil->s[1]=nil;
  183. 183 nil->tot=0;
  184. 184 nil->code=nil->v=-2;
  185. 185
  186. 186 n=getint();
  187. 187 m=getint();
  188. 188
  189. 189 T=new SplayTree*[n];
  190. 190 for(int i=0;i<n;i++)
  191. 191 {
  192. 192 T[i]=new SplayTree;
  193. 193 T[i]->Insert(getint(),i);
  194. 194 }
  195. 195
  196. 196 for(int i=0;i<m;i++)
  197. 197 {
  198. 198 int a=getint()-1;
  199. 199 int b=getint()-1;
  200. 200 if(T[a]!=T[b]) Merge(T[a],T[b]);
  201. 201 }
  202. 202
  203. 203 q=getint();
  204. 204 for(int i=0;i<q;i++)
  205. 205 {
  206. 206 char c=getchar();
  207. 207 while(c!=\'B\' && c!=\'Q\') c=getchar();
  208. 208 int a=getint()-1;
  209. 209 int b=getint()-1;
  210. 210 if(c==\'B\')
  211. 211 {
  212. 212 if(T[a]!=T[b]) Merge(T[a],T[b]);
  213. 213 }
  214. 214 else if(c==\'Q\')
  215. 215 {
  216. 216 if(a<0 || a>=n) printf("%d\n",-1);
  217. 217 else
  218. 218 printf("%d\n",T[a]->FindRank(b+1)->code+1);
  219. 219 }
  220. 220 }
  221. 221
  222. 222 return 0;
  223. 223 }

View Code

 

 

启发式合并两棵SplayTree.

代码好长….

速度好慢…..

o(╯□╰)o……

 

 


Treap

虽然说蛮好玩的…..

速度快得不行….

但是感觉代码复杂度跟splay一样啊…..

AC BZOJ3224 普通平衡树

排序Treap.

 

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 typedef unsigned int uint;
  18. 18 typedef long long int ll;
  19. 19 typedef unsigned long long int ull;
  20. 20 typedef double db;
  21. 21
  22. 22 using namespace std;
  23. 23
  24. 24 inline int getint()
  25. 25 {
  26. 26 int res=0;
  27. 27 char c=getchar();
  28. 28 bool mi=false;
  29. 29 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  30. 30 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  31. 31 return mi ? -res : res;
  32. 32 }
  33. 33 inline ll getll()
  34. 34 {
  35. 35 ll res=0;
  36. 36 char c=getchar();
  37. 37 bool mi=false;
  38. 38 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  39. 39 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  40. 40 return mi ? -res : res;
  41. 41 }
  42. 42
  43. 43 db eps=1e-80;
  44. 44 inline bool feq(db a,db b)
  45. 45 { return fabs(a-b)<eps; }
  46. 46
  47. 47 template<typename Type>
  48. 48 inline Type avg(const Type a,const Type b)
  49. 49 { return a+((b-a)/2); }
  50. 50
  51. 51 //===================================================================
  52. 52 //===================================================================
  53. 53 //===================================================================
  54. 54 //===================================================================
  55. 55
  56. 56 int INF=(1<<30)-1;
  57. 57
  58. 58 int getrand()
  59. 59 { return rand()+32768*rand(); }
  60. 60
  61. 61 int t[105000];
  62. 62 int tot[105000];
  63. 63 int hp[105000];
  64. 64 int s[105000][2];
  65. 65 int f[105000];
  66. 66 int ntot=1;
  67. 67
  68. 68 int n;
  69. 69
  70. 70 void update(int x)
  71. 71 { if(x) tot[x] = tot[s[x][0]] + tot[s[x][1]] +1; }
  72. 72
  73. 73 int root=0;
  74. 74 void rot(int x)
  75. 75 {
  76. 76 int y=f[x];
  77. 77 int k=(x==s[y][0]);
  78. 78 s[y][!k]=s[x][k];
  79. 79 if(s[x][k]) f[s[x][k]]=y;
  80. 80 f[x]=f[y];
  81. 81 if(y==s[f[y]][0]) s[f[y]][0]=x;
  82. 82 else if(y==s[f[y]][1]) s[f[y]][1]=x;
  83. 83 f[y]=x;
  84. 84 s[x][k]=y;
  85. 85 update(y);
  86. 86 update(x);
  87. 87 if(!f[x]) root=x;
  88. 88 }
  89. 89
  90. 90 int lift(int x)
  91. 91 { while(f[x] && hp[x]<hp[f[x]]) rot(x);}
  92. 92
  93. 93 void Insert(int v)
  94. 94 {
  95. 95 if(!root)
  96. 96 { t[ntot]=v; tot[ntot]=1; root=ntot++; return ; }
  97. 97
  98. 98 int x=root;
  99. 99 int k=-1;
  100. 100 while(true)
  101. 101 {
  102. 102 tot[x]++;
  103. 103 if(v>t[x])
  104. 104 {
  105. 105 if(!s[x][1]) { k=1; break; }
  106. 106 x=s[x][1];
  107. 107 }
  108. 108 else
  109. 109 {
  110. 110 if(!s[x][0]) { k=0; break; }
  111. 111 x=s[x][0];
  112. 112 }
  113. 113 }
  114. 114
  115. 115 f[ntot]=x;
  116. 116 tot[ntot]=1;
  117. 117 hp[ntot]=getrand();
  118. 118 t[ntot]=v;
  119. 119 s[x][k]=ntot++;
  120. 120 lift(s[x][k]);
  121. 121 }
  122. 122
  123. 123 int FindRank(int k)
  124. 124 {
  125. 125 int x=root;
  126. 126 int y=0;
  127. 127 while(x)
  128. 128 {
  129. 129 y=x;
  130. 130 if(k==tot[s[x][0]]+1) break;
  131. 131 if(k<=tot[s[x][0]])
  132. 132 x=s[x][0];
  133. 133 else
  134. 134 {
  135. 135 k-=tot[s[x][0]]+1;
  136. 136 x=s[x][1];
  137. 137 }
  138. 138 }
  139. 139 return y;
  140. 140 }
  141. 141
  142. 142 int Find(int v)
  143. 143 {
  144. 144 int x=root;
  145. 145 while(true)
  146. 146 {
  147. 147 if(t[x]==v) return x;
  148. 148 else x=s[x][v>=t[x]];
  149. 149 }
  150. 150 return -1;
  151. 151 }
  152. 152
  153. 153 int Rank(int v)
  154. 154 {
  155. 155 int x=root;
  156. 156 int r=0;
  157. 157 while(x)
  158. 158 {
  159. 159 if(v>t[x])
  160. 160 {
  161. 161 r+=tot[s[x][0]]+1;
  162. 162 x=s[x][1];
  163. 163 }
  164. 164 else
  165. 165 x=s[x][0];
  166. 166 }
  167. 167 return r;
  168. 168 }
  169. 169
  170. 170 void Delete(int x)
  171. 171 {
  172. 172 while(s[x][0] || s[x][1])
  173. 173 {
  174. 174 if(s[x][0]) rot(s[x][0]);
  175. 175 else rot(s[x][1]);
  176. 176 }
  177. 177
  178. 178 if(!f[x]) root=0;
  179. 179 else
  180. 180 s[f[x]][x==s[f[x]][1]]=0;
  181. 181
  182. 182 x=f[x];
  183. 183 while(x) tot[x]--,x=f[x];
  184. 184 }
  185. 185
  186. 186 int Prefix(int v)
  187. 187 {
  188. 188 int x=root;
  189. 189 int r=-INF;
  190. 190 while(x)
  191. 191 {
  192. 192 if(t[x]<v) r=t[x];
  193. 193 x=s[x][v>t[x]];
  194. 194 }
  195. 195 return r;
  196. 196 }
  197. 197
  198. 198 int Suffix(int v)
  199. 199 {
  200. 200 int x=root;
  201. 201 int r=INF;
  202. 202 while(x)
  203. 203 {
  204. 204 if(t[x]>v) r=t[x];
  205. 205 x=s[x][v>=t[x]];
  206. 206 }
  207. 207 return r;
  208. 208 }
  209. 209
  210. 210 int a[105000];
  211. 211
  212. 212 int main()
  213. 213 {
  214. 214 srand(23333);
  215. 215
  216. 216 n=getint();
  217. 217 for(int i=0;i<n;i++)
  218. 218 {
  219. 219 int c=getint();
  220. 220 switch(c)
  221. 221 {
  222. 222 case 1: Insert(getint()); break;
  223. 223 case 2: Delete(Find(getint())); break;
  224. 224 case 3: printf("%d\n",Rank(getint())+1); break;
  225. 225 case 4: printf("%d\n",t[FindRank(getint())]); break;
  226. 226 case 5: printf("%d\n",Prefix(getint())); break;
  227. 227 default: printf("%d\n",Suffix(getint())); break;
  228. 228 }
  229. 229 }
  230. 230
  231. 231 return 0;
  232. 232 }

View Code

 

 

 


线段树

AC BZOJ 3212 A Simple Problem 经典题

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 typedef unsigned int uint;
  18. 18 typedef long long int ll;
  19. 19 typedef unsigned long long int ull;
  20. 20 typedef double db;
  21. 21
  22. 22 using namespace std;
  23. 23
  24. 24 inline int getint()
  25. 25 {
  26. 26 int res=0;
  27. 27 char c=getchar();
  28. 28 bool mi=false;
  29. 29 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  30. 30 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  31. 31 return mi ? -res : res;
  32. 32 }
  33. 33 inline ll getll()
  34. 34 {
  35. 35 ll res=0;
  36. 36 char c=getchar();
  37. 37 bool mi=false;
  38. 38 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  39. 39 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  40. 40 return mi ? -res : res;
  41. 41 }
  42. 42
  43. 43 //==============================================================================
  44. 44 //==============================================================================
  45. 45 //==============================================================================
  46. 46 //==============================================================================
  47. 47
  48. 48
  49. 49 int n,m;
  50. 50 int a[105000];
  51. 51 ll t[405000];
  52. 52 ll tag[405000];
  53. 53 void Build(int x=1,int l=0,int r=n-1)
  54. 54 {
  55. 55 if(l==r) { t[x]=a[l]; return ; }
  56. 56 int mid=(l+r)>>1;
  57. 57 Build(x<<1,l,mid); Build(x<<1|1,mid+1,r);
  58. 58 t[x]=t[x<<1]+t[x<<1|1];
  59. 59 }
  60. 60 int cl,cr,cv;
  61. 61 void Change(int x=1,int l=0,int r=n-1)
  62. 62 {
  63. 63 if(cr<l || r<cl) return ;
  64. 64 if(cl<=l && r<=cr) { tag[x]+=cv; return ; }
  65. 65 int mid=(l+r)>>1;
  66. 66 Change(x<<1,l,mid),Change(x<<1|1,mid+1,r);
  67. 67 t[x]=t[x<<1]+tag[x<<1]*(mid-l+1)+t[x<<1|1]+tag[x<<1|1]*(r-mid);
  68. 68 }
  69. 69 int ql,qr;
  70. 70 ll Query(int x=1,int l=0,int r=n-1)
  71. 71 {
  72. 72 if(qr<l || r<ql) return 0;
  73. 73 if(ql<=l && r<=qr) return t[x]+tag[x]*(r-l+1);
  74. 74 int mid=(l+r)>>1;
  75. 75 return Query(x<<1,l,mid)+Query(x<<1|1,mid+1,r)+
  76. 76 tag[x]*(min(r,qr)-max(l,ql)+1);
  77. 77 }
  78. 78 int main()
  79. 79 {
  80. 80 n=getint();
  81. 81 m=getint();
  82. 82 for(int i=0;i<n;i++)
  83. 83 a[i]=getint();
  84. 84 Build();
  85. 85 for(int i=0;i<m;i++)
  86. 86 {
  87. 87 char c=getchar();
  88. 88 while(c!=\'Q\' && c!=\'C\') c=getchar();
  89. 89 if(c==\'C\')
  90. 90 {
  91. 91 cl=getint()-1;
  92. 92 cr=getint()-1;
  93. 93 cv=getint();
  94. 94 Change();
  95. 95 }
  96. 96 else //if(c==\'Q\')
  97. 97 {
  98. 98 ql=getint()-1;
  99. 99 qr=getint()-1;
  100. 100 printf("%lld\n",Query());
  101. 101 }
  102. 102 }
  103. 103
  104. 104 return 0;
  105. 105 }

View Code

区间加,区间求和.永久性lazytag.常数大概是普通线段树的四分之一…….

 

AC BZOJ 3685 用线段树做平衡树查询

 

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 typedef unsigned int uint;
  18. 18 typedef long long int ll;
  19. 19 typedef unsigned long long int ull;
  20. 20 typedef double db;
  21. 21 typedef long double ldb;
  22. 22
  23. 23 using namespace std;
  24. 24
  25. 25 inline int getint()
  26. 26 {
  27. 27 int res=0;
  28. 28 char c=getchar();
  29. 29 bool mi=false;
  30. 30 while((c<\'0\' || c>\'9\')/* && !feof(stdin)*/) mi=(c==\'-\'),c=getchar();
  31. 31 while(\'0\'<=c && c<=\'9\'/* && !feof(stdin)*/) res=res*10+c-\'0\',c=getchar();
  32. 32 return mi ? -res : res;
  33. 33 }
  34. 34 inline ll getll()
  35. 35 {
  36. 36 ll res=0;
  37. 37 char c=getchar();
  38. 38 bool mi=false;
  39. 39 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  40. 40 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  41. 41 return mi ? -res : res;
  42. 42 }
  43. 43
  44. 44 //==============================================================================
  45. 45 //==============================================================================
  46. 46 //==============================================================================
  47. 47 //==============================================================================
  48. 48
  49. 49 int n;
  50. 50 int L,R;
  51. 51 int t[4005000];
  52. 52
  53. 53 int cp,cv;
  54. 54 void Change(int x=1,int l=L,int r=R)
  55. 55 {
  56. 56 if(l==r) { t[x]=cv; return ; }
  57. 57 int mid=(l+r)>>1;
  58. 58 if(cp<=mid) Change(x<<1,l,mid);
  59. 59 else Change(x<<1|1,mid+1,r);
  60. 60 t[x]=t[x<<1]+t[x<<1|1];
  61. 61 }
  62. 62
  63. 63 int GetMin(int x=1,int l=L,int r=R)
  64. 64 {
  65. 65 if(!t[x]) return -1;
  66. 66 while(l!=r)
  67. 67 {
  68. 68 int mid=(l+r)>>1;
  69. 69 if(t[x<<1]) { r=mid; x<<=1; }
  70. 70 else { l=mid+1; x=x<<1|1; }
  71. 71 }
  72. 72 return l;
  73. 73 }
  74. 74
  75. 75 int GetMax(int x=1,int l=L,int r=R)
  76. 76 {
  77. 77 if(!t[x]) return -1;
  78. 78 while(l!=r)
  79. 79 {
  80. 80 int mid=(l+r)>>1;
  81. 81 if(t[x<<1|1]) { l=mid+1; x=x<<1|1; }
  82. 82 else { r=mid; x<<=1; }
  83. 83 }
  84. 84 return l;
  85. 85 }
  86. 86
  87. 87 int Exist(int p,int x=1,int l=L,int r=R)
  88. 88 {
  89. 89 if(!t[x]) return -1;
  90. 90 while(l!=r)
  91. 91 {
  92. 92 int mid=(l+r)>>1;
  93. 93 if(p<=mid) { x<<=1; r=mid; }
  94. 94 else { x=x<<1|1; l=mid+1; }
  95. 95 if(!t[x]) return -1;
  96. 96 }
  97. 97 return 1;
  98. 98 }
  99. 99
  100. 100 int Prefix(int v,int x=1,int l=L,int r=R)
  101. 101 {
  102. 102 int y=0,yl=0,yr=0;
  103. 103 while(l!=r)
  104. 104 {
  105. 105 int mid=(l+r)>>1;
  106. 106 if(v<=mid) { x<<=1; r=mid; }
  107. 107 else
  108. 108 {
  109. 109 if(t[x<<1]) { y=x<<1; yl=l; yr=mid; }
  110. 110 x=x<<1|1; l=mid+1;
  111. 111 }
  112. 112 }
  113. 113 return y ? GetMax(y,yl,yr) : -1;
  114. 114 }
  115. 115
  116. 116 int Suffix(int v,int x=1,int l=L,int r=R)
  117. 117 {
  118. 118 int y=0,yl=0,yr=0;
  119. 119 while(l!=r)
  120. 120 {
  121. 121 int mid=(l+r)>>1;
  122. 122 if(v<=mid)
  123. 123 {
  124. 124 if(t[x<<1|1]) { y=x<<1|1; yl=mid+1; yr=r; }
  125. 125 x<<=1; r=mid;
  126. 126 }
  127. 127 else { x=x<<1|1; l=mid+1; }
  128. 128 }
  129. 129 return y ? GetMin(y,yl,yr) : -1;
  130. 130 }
  131. 131
  132. 132 int main()
  133. 133 {
  134. 134 n=getint();
  135. 135 L=-1; R=n+1;
  136. 136 int m=getint();
  137. 137 for(int i=0;i<m;i++)
  138. 138 {
  139. 139 int c=getint();
  140. 140 switch(c)
  141. 141 {
  142. 142 case 1: cp=getint(); cv=1; Change(); break;
  143. 143 case 2: cp=getint(); cv=0; Change(); break;
  144. 144 case 3: printf("%d\n",GetMin()); break;
  145. 145 case 4: printf("%d\n",GetMax()); break;
  146. 146 case 5: printf("%d\n",Prefix(getint())); break;
  147. 147 case 6: printf("%d\n",Suffix(getint())); break;
  148. 148 case 7: printf("%d\n",Exist(getint()));
  149. 149 default:break;
  150. 150 }
  151. 151 }
  152. 152
  153. 153 return 0;
  154. 154 }

View Code

注意前驱和后继的写法:

想象一下前缀的搜索过程,我们先搜索到询问数字的代表节点,然后回退,如果左子树非空就进入这棵左子树并一直往右往下走.

先写一个GetMax和GetMin函数,表示找到某一棵子树中最靠右的存在的节点.

然后查询前驱(或后继)时,考虑记下一个”最右(左)可行子树y”.就是说

我们遍历从根到所查询的值的节点的路径,如果遍历过程中往右(左)走了,并且当前节点左(右)子树非空,

那么拿当前节点的左(右)子树替换掉y,这样我们就得到了”最靠右(左)的可行子树”.

然后在这棵子树中GetMax(GetMin)就行了.

 

 


可持久化线段树

AC VIJOS 1081 野生动物园

一道非常裸的区间k大

  1. 1 const int INF=(1<<30)-1;
  2. 2
  3. 3 struct node
  4. 4 {
  5. 5 int t;
  6. 6 node*l,*r;
  7. 7 node(){ t=0; l=r=NULL; }
  8. 8
  9. 9 void update()
  10. 10 { t=l->t+r->t; }
  11. 11 }pool[4000000];
  12. 12 int nt;
  13. 13 node*newnode()
  14. 14 { return &pool[nt++]; }
  15. 15
  16. 16 node*nil;
  17. 17
  18. 18 node*root[100050];
  19. 19
  20. 20 void SegmentTreeInit(int size)
  21. 21 {
  22. 22 nil=newnode();
  23. 23 nil->l=nil->r=nil;
  24. 24 nil->t=0;
  25. 25 for(int i=0;i<=size;i++)
  26. 26 root[i]=nil;
  27. 27 }
  28. 28
  29. 29 int cp;
  30. 30 node*Change(node*x,node*y,int l,int r)
  31. 31 {
  32. 32 if(cp<l || r<cp) return y;
  33. 33 x=newnode();
  34. 34 if(l==r) { x->t=1+y->t; return x; }
  35. 35 int mid=(l+r)>>1;
  36. 36 x->l=Change(x->l,y->l,l,mid);
  37. 37 x->r=Change(x->r,y->r,mid+1,r);
  38. 38 x->update();
  39. 39 return x;
  40. 40 }
  41. 41 void Change(int i,int j,int pos)
  42. 42 { cp=pos; root[i]=Change(nil,root[j],0,INF); }
  43. 43
  44. 44 int Query(int ql,int qr,int k)
  45. 45 {
  46. 46 node*x=root[ql],*y=root[qr];
  47. 47 int l=0,r=INF;
  48. 48 while(l!=r)
  49. 49 {
  50. 50 int mid=(l+r)>>1;
  51. 51 if( k<= x->l->t - y->l->t )
  52. 52 r=mid,x=x->l,y=y->l;
  53. 53 else
  54. 54 {
  55. 55 k-=x->l->t-y->l->t;
  56. 56 l=mid+1,x=x->r,y=y->r;
  57. 57 }
  58. 58 }
  59. 59 return l;
  60. 60 }
  61. 61
  62. 62
  63. 63
  64. 64 int n;
  65. 65
  66. 66
  67. 67
  68. 68 int main()
  69. 69 {
  70. 70
  71. 71 int q;
  72. 72 scanf("%d",&n);
  73. 73 scanf("%d",&q);
  74. 74
  75. 75 SegmentTreeInit(n);
  76. 76
  77. 77
  78. 78 for(int i=0;i<n;i++)
  79. 79 {
  80. 80 int c;
  81. 81 scanf("%d",&c);
  82. 82 cp=c;
  83. 83 root[i+1]=Change(root[i+1],root[i],0,INF);
  84. 84 }
  85. 85
  86. 86
  87. 87 for(int i=0;i<q;i++)
  88. 88 {
  89. 89 int a,b,k;
  90. 90 scanf("%d%d%d",&a,&b,&k);
  91. 91 printf("%d\n",Query(b,a-1,k));
  92. 92 }
  93. 93
  94. 94 return 0;
  95. 95 }

View Code

要点1.使用nil节点可以省一点代码

要点2.千万注意空间开销.一般为nlogv级别,数组经常开上百万(懒得写离散化系列)

要点3.注意前缀和的写法. tree[R]-tree[L-1]. 这就要求root[0]=nil.

要点4.智商捉急表示普通查找操作总是写错…splay也一样…..思考…思考……写之前一定要想好….

 

AC BZOJ 3932 加强版的主席树,以时间轴为询问区间,插入一个值,删除一个值.

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 typedef unsigned int uint;
  18. 18 typedef long long int ll;
  19. 19 typedef unsigned long long int ull;
  20. 20 typedef double db;
  21. 21
  22. 22 using namespace std;
  23. 23
  24. 24 inline int getint()
  25. 25 {
  26. 26 int res=0;
  27. 27 char c=getchar();
  28. 28 bool mi=false;
  29. 29 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  30. 30 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  31. 31 return mi ? -res : res;
  32. 32 }
  33. 33 inline ll getll()
  34. 34 {
  35. 35 ll res=0;
  36. 36 char c=getchar();
  37. 37 bool mi=false;
  38. 38 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  39. 39 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  40. 40 return mi ? -res : res;
  41. 41 }
  42. 42
  43. 43 //==============================================================================
  44. 44 //==============================================================================
  45. 45 //==============================================================================
  46. 46 //==============================================================================
  47. 47
  48. 48 const int INF=10000001;
  49. 49
  50. 50 struct node*nil;
  51. 51 struct node
  52. 52 {
  53. 53 int t;
  54. 54 ll v;
  55. 55 node*l,*r;
  56. 56
  57. 57 void update()
  58. 58 { t = l->t + r->t; v = l->v + r->v; }
  59. 59
  60. 60 };
  61. 61 int cnt=10000;
  62. 62 node*nt;
  63. 63 node*newnode()
  64. 64 {
  65. 65 if(cnt==10000){ cnt=0; nt=new node[10000]; }
  66. 66 nt->t=nt->v=0;
  67. 67 nt->l=nt->r=nil;
  68. 68 cnt++;
  69. 69 return nt++;
  70. 70 }
  71. 71
  72. 72 int n,m;
  73. 73
  74. 74 node*root[105000];
  75. 75
  76. 76 struct operation
  77. 77 {
  78. 78 int p; //time block
  79. 79 int v; //value
  80. 80 bool type; //0:add 1:dec
  81. 81
  82. 82 }op[205000];
  83. 83
  84. 84 bool cmp(const operation&a,const operation&b)
  85. 85 { return a.p<b.p; }
  86. 86
  87. 87
  88. 88 int cp,cv;
  89. 89 node*Change(node*y,int l,int r)
  90. 90 {
  91. 91 if(cp<l || r<cp) return y;
  92. 92 node*x=newnode();
  93. 93 if(l==r) { x->t=y->t+cv; x->v=y->v+cp*cv; return x; }
  94. 94 int mid=(l+r)>>1;
  95. 95 x->l=Change(y->l,l,mid);
  96. 96 x->r=Change(y->r,mid+1,r);
  97. 97 x->update();
  98. 98 return x;
  99. 99 }
  100. 100
  101. 101 node*Change(int p,int v,node*pre)
  102. 102 { cp=p; cv=v; return Change(pre,0,INF); }
  103. 103
  104. 104
  105. 105 int ql,qr;
  106. 106
  107. 107 ll rest;
  108. 108 ll last;
  109. 109 int Query(int k,node*x) //x-y. query for the kth node.
  110. 110 {
  111. 111 if(x->t<k) return INF;
  112. 112 int l=0,r=INF;
  113. 113 while(l!=r)
  114. 114 {
  115. 115 int mid=(l+r)>>1;
  116. 116 if(k<=x->l->t)
  117. 117 {
  118. 118 x=x->l;
  119. 119 r=mid;
  120. 120 }
  121. 121 else
  122. 122 {
  123. 123 k-=x->l->t;
  124. 124 x=x->r;
  125. 125 l=mid+1;
  126. 126 }
  127. 127 }
  128. 128 rest=x->t-k;
  129. 129 last=x->v/x->t;
  130. 130 return l;
  131. 131 }
  132. 132
  133. 133 ll Query(node*x,int l=0,int r=INF) //x-y. query for sum.
  134. 134 {
  135. 135 if(qr<l || r<ql) return 0;
  136. 136 if(ql<=l && r<=qr) return x->v;
  137. 137 int mid=(l+r)>>1;
  138. 138 return Query(x->l,l,mid) + Query(x->r,mid+1,r);
  139. 139 }
  140. 140
  141. 141 int main()
  142. 142 {
  143. 143 nil=newnode();
  144. 144 nil->l=nil->r=nil;
  145. 145
  146. 146 n=getint();
  147. 147 m=getint();
  148. 148 for(int i=0;i<n;i++)
  149. 149 {
  150. 150 int a=getint();
  151. 151 int b=getint();
  152. 152 int c=getint();
  153. 153 op[i].p=a; op[i].v=c; op[i].type=0;
  154. 154 op[i+n].p=b+1; op[i+n].v=c; op[i+n].type=1;
  155. 155 }
  156. 156
  157. 157 for(int i=0;i<=103000;i++) root[i]=nil;
  158. 158
  159. 159 sort(op,op+2*n,cmp);
  160. 160
  161. 161 int cur=0;
  162. 162 for(int i=1;i<=103000;i++)
  163. 163 {
  164. 164 root[i]=root[i-1];
  165. 165 while(op[cur].p==i && cur<2*n)
  166. 166 {
  167. 167 root[i]=Change(op[cur].v,op[cur].type==0 ? 1 : -1,root[i]);
  168. 168 cur++;
  169. 169 }
  170. 170 }
  171. 171
  172. 172 ll pre=1;
  173. 173
  174. 174 ql=0;
  175. 175 for(int i=0;i<m;i++)
  176. 176 {
  177. 177 int p=getint();
  178. 178 int a=getint();
  179. 179 int b=getint();
  180. 180 int c=getint();
  181. 181 ll k=((ll)a*pre+(ll)b)%c+1;
  182. 182 qr=Query(k,root[p]);
  183. 183 printf("%lld\n",pre=(Query(root[p])-rest*last));
  184. 184 }
  185. 185
  186. 186
  187. 187 return 0;
  188. 188 }

View Code

所以说啊….我写的可持久化线段树也没那么容易RE啊…..COT怎么就是A不了呢…..

WA了一发是因为没有想清楚前k个的含义,那些值与第k个元素相等但不计入结果的元素没有考虑进去….

哎……这个算智商么……

 

AC BZOJ3674 可持久化并查集加强版

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 typedef unsigned int uint;
  18. 18 typedef long long int ll;
  19. 19 typedef unsigned long long int ull;
  20. 20 typedef double db;
  21. 21
  22. 22 using namespace std;
  23. 23
  24. 24 inline int getint()
  25. 25 {
  26. 26 int res=0;
  27. 27 char c=getchar();
  28. 28 bool mi=false;
  29. 29 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  30. 30 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  31. 31 return mi ? -res : res;
  32. 32 }
  33. 33 inline ll getll()
  34. 34 {
  35. 35 ll res=0;
  36. 36 char c=getchar();
  37. 37 bool mi=false;
  38. 38 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  39. 39 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  40. 40 return mi ? -res : res;
  41. 41 }
  42. 42
  43. 43 //==============================================================================
  44. 44 //==============================================================================
  45. 45 //==============================================================================
  46. 46 //==============================================================================
  47. 47
  48. 48
  49. 49 struct node*nil;
  50. 50 struct node
  51. 51 {
  52. 52 int v;
  53. 53 node*l,*r;
  54. 54 };
  55. 55 int ncnt=4000;
  56. 56 node*nt;
  57. 57 node*newnode()
  58. 58 {
  59. 59 if(ncnt==4000) { ncnt=0; nt=new node[4000]; }
  60. 60 nt->v=0;
  61. 61 nt->l=nt->r=nil;
  62. 62 ncnt++;
  63. 63 return nt++;
  64. 64 }
  65. 65
  66. 66 node*root[405000]; //operations.
  67. 67
  68. 68 int n,m;
  69. 69
  70. 70 int cp,cv;
  71. 71 node*Change(node*y,int l=0,int r=n+1)
  72. 72 {
  73. 73 if(cp<l || r<cp) return y;
  74. 74 node*x=newnode();
  75. 75 if(l==r) { x->v=cv; return x; }
  76. 76 int mid=(l+r)>>1;
  77. 77 x->l=Change(y->l,l,mid);
  78. 78 x->r=Change(y->r,mid+1,r);
  79. 79 return x;
  80. 80 }
  81. 81
  82. 82 int Get(node*x,int p)
  83. 83 {
  84. 84 int l=0,r=n+1;
  85. 85 while(l!=r)
  86. 86 {
  87. 87 int mid=(l+r)>>1;
  88. 88 if(p<=mid)
  89. 89 x=x->l,r=mid;
  90. 90 else
  91. 91 x=x->r,l=mid+1;
  92. 92 }
  93. 93 return x->v;
  94. 94 }
  95. 95
  96. 96 node*Build(int l=0,int r=n+1)
  97. 97 {
  98. 98 node*x=newnode();
  99. 99 if(l==r) { x->v=l; return x; }
  100. 100 int mid=(l+r)>>1;
  101. 101 x->l=Build(l,mid);
  102. 102 x->r=Build(mid+1,r);
  103. 103 return x;
  104. 104 }
  105. 105
  106. 106 int findf(node*&t,int x)
  107. 107 {
  108. 108 int f=Get(t,x);
  109. 109 if(f==x) return x;
  110. 110 int ff=findf(t,f);
  111. 111 cp=x; cv=ff;
  112. 112 t=Change(t);
  113. 113 return ff;
  114. 114 }
  115. 115
  116. 116 int main()
  117. 117 {
  118. 118 nil=newnode();
  119. 119 nil->v=0;
  120. 120 nil->l=nil->r=nil;
  121. 121
  122. 122 n=getint();
  123. 123 m=getint();
  124. 124
  125. 125 root[0]=Build();
  126. 126
  127. 127 int lastans=0;
  128. 128
  129. 129 for(int i=1;i<=m;i++)
  130. 130 {
  131. 131 int c=getint();
  132. 132
  133. 133 if(c==1) //Merge
  134. 134 {
  135. 135 int a=getint();
  136. 136 int b=getint();
  137. 137
  138. 138 root[i]=root[i-1];
  139. 139 int fa=findf(root[i],a);
  140. 140 int fb=findf(root[i],b);
  141. 141 if(fa!=fb)
  142. 142 {
  143. 143 cp=fa;
  144. 144 cv=fb;
  145. 145 root[i]=Change(root[i]);
  146. 146 }
  147. 147 }
  148. 148 else if(c==2) //Back
  149. 149 {
  150. 150 int k=getint()^lastans;
  151. 151 root[i]=root[k];
  152. 152 }
  153. 153 else if(c==3) //Query
  154. 154 {
  155. 155 int a=getint()^lastans;
  156. 156 int b=getint()^lastans;
  157. 157 root[i]=root[i-1];
  158. 158 int fa=findf(root[i],a);
  159. 159 int fb=findf(root[i],b);
  160. 160 printf("%d\n",lastans=(fa==fb));
  161. 161 }
  162. 162 }
  163. 163
  164. 164 return 0;
  165. 165 }

View Code

好吧,不知怎么的就A了…..

加强版的话,不加路径压缩会TLE哦…..

 

AC BZOJ2588 SPOJ:COT Count On A Tree

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 typedef unsigned int uint;
  18. 18 typedef long long int ll;
  19. 19 typedef unsigned long long int ull;
  20. 20 typedef double db;
  21. 21 typedef long double ldb;
  22. 22
  23. 23 using namespace std;
  24. 24
  25. 25 inline int getint()
  26. 26 {
  27. 27 int res=0;
  28. 28 char c=getchar();
  29. 29 bool mi=false;
  30. 30 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  31. 31 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  32. 32 return mi ? -res : res;
  33. 33 }
  34. 34 inline ll getll()
  35. 35 {
  36. 36 ll res=0;
  37. 37 char c=getchar();
  38. 38 bool mi=false;
  39. 39 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  40. 40 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  41. 41 return mi ? -res : res;
  42. 42 }
  43. 43
  44. 44 //==============================================================================
  45. 45 //==============================================================================
  46. 46 //==============================================================================
  47. 47 //==============================================================================
  48. 48
  49. 49 struct edge
  50. 50 { int in; edge*nxt; };
  51. 51 int ecnt=2000; edge*et;
  52. 52 edge*eds[105000];
  53. 53 void addedge(int a,int b)
  54. 54 {
  55. 55 if(ecnt==2000) { ecnt=0; et=new edge[2000]; }
  56. 56 et->in=b; et->nxt=eds[a]; eds[a]=et++; ecnt++;
  57. 57 }
  58. 58 #define FOREACH_EDGE(e,x) for(edge*e=eds[x];e;e=e->nxt)
  59. 59
  60. 60 int v[105000]; int lim=0;
  61. 61
  62. 62 struct node*nil;
  63. 63 struct node
  64. 64 { int t; node*l,*r; void update(){t=l->t+r->t;} };
  65. 65 int ncnt=4000; node*nt;
  66. 66 node*newnode()
  67. 67 {
  68. 68 if(ncnt==4000) { ncnt=0; nt=new node[4000]; }
  69. 69 ncnt++; return nt++;
  70. 70 }
  71. 71 int cp;
  72. 72 node*Insert(node*y,int l=0,int r=lim-1)
  73. 73 {
  74. 74 node*x=newnode();
  75. 75 if(l==r) { x->l=x->r=nil; x->t=y->t+1; return x; }
  76. 76 int mid=(l+r)>>1;
  77. 77 x->l= cp<=mid ? Insert(y->l,l,mid) : y->l;
  78. 78 x->r= cp>mid ? Insert(y->r,mid+1,r) : y->r;
  79. 79 x->update(); return x;
  80. 80 }
  81. 81
  82. 82 int n,m,q;
  83. 83
  84. 84 int a[105000];
  85. 85 int dep[105000];
  86. 86 int f[105000];
  87. 87 node*root[105000];
  88. 88 int ch[105000]; int chtot=0;
  89. 89 int h[105000];
  90. 90
  91. 91 int Build(int x)
  92. 92 {
  93. 93 //printf("%d\n",x);
  94. 94 int sum=0;
  95. 95 int mxp=0;
  96. 96 int mx=0;
  97. 97 FOREACH_EDGE(e,x)
  98. 98 if(e->in!=f[x])
  99. 99 {
  100. 100 dep[e->in]=dep[x]+1;
  101. 101 f[e->in]=x;
  102. 102 cp=a[e->in]; root[e->in]=Insert(root[x]);
  103. 103 int v=Build(e->in);
  104. 104 if(v>mx) mx=v,mxp=e->in;
  105. 105 sum+=v;
  106. 106 }
  107. 107
  108. 108 if(mxp) ch[x]=ch[mxp];
  109. 109 else ch[x]=chtot++;
  110. 110 h[ch[x]]=x;
  111. 111
  112. 112 return sum+1;
  113. 113 }
  114. 114
  115. 115 int getlca(int a,int b)
  116. 116 {
  117. 117 while(ch[a]!=ch[b])
  118. 118 {
  119. 119 if(dep[h[ch[a]]]<dep[h[ch[b]]]) swap(a,b);
  120. 120 a=f[h[ch[a]]];
  121. 121 }
  122. 122 return dep[a]<dep[b] ? a : b;
  123. 123 }
  124. 124
  125. 125 int Query(int a,int b,int k)
  126. 126 {
  127. 127 node*c[4];
  128. 128 c[0]=root[a];
  129. 129 c[1]=root[b];
  130. 130 int lca=getlca(a,b);
  131. 131 c[2]=root[lca];
  132. 132 c[3]=root[f[lca]];
  133. 133 int l=0,r=lim-1;
  134. 134 while(l!=r)
  135. 135 {
  136. 136 int mid=(l+r)>>1;
  137. 137 int lv=c[0]->l->t + c[1]->l->t - c[2]->l->t -c[3]->l->t;
  138. 138 if(k<=lv)
  139. 139 {
  140. 140 for(int i=0;i<4;i++) c[i]=c[i]->l;
  141. 141 r=mid;
  142. 142 }
  143. 143 else
  144. 144 {
  145. 145 k-=lv;
  146. 146 for(int i=0;i<4;i++) c[i]=c[i]->r;
  147. 147 l=mid+1;
  148. 148 }
  149. 149 }
  150. 150 return l;
  151. 151 }
  152. 152
  153. 153 int main()
  154. 154 {
  155. 155 nil=new node;
  156. 156 nil->t=0;
  157. 157 nil->l=nil->r=nil;
  158. 158
  159. 159 n=getint();
  160. 160 m=n-1;
  161. 161 q=getint();
  162. 162 for(int i=0;i<n;i++) v[i]=a[i]=getint();
  163. 163 sort(v,v+n);
  164. 164 lim=int(unique(v,v+n)-v);
  165. 165 for(int i=0;i<n;i++)
  166. 166 a[i]=int(lower_bound(v,v+lim,a[i])-v);
  167. 167
  168. 168 for(int i=0;i<m;i++)
  169. 169 {
  170. 170 int a=getint()-1;
  171. 171 int b=getint()-1;
  172. 172 addedge(a,b); addedge(b,a);
  173. 173 }
  174. 174 addedge(n,0); //node n is a sepcial dummy node.
  175. 175 root[n]=nil; f[n]=n;
  176. 176 Build(n);
  177. 177
  178. 178 int lst=0;
  179. 179 for(int i=0;i<q;i++)
  180. 180 {
  181. 181 int a=getint();
  182. 182 int b=getint()-1;
  183. 183 int k=getint();
  184. 184 a=a^lst;
  185. 185 a--;
  186. 186 printf("%d",lst=v[Query(a,b,k)]);
  187. 187 if(i!=q-1) printf("\n");
  188. 188 }
  189. 189
  190. 190 return 0;
  191. 191 }

View Code

终于A了啊…..

离散化 + HLD-LCA 拿到了rank3 2333333

 

 

 

 


树套树

AC VIJOS 1665

树状数组 套 动态开点的权值线段树

题目就是裸的带修改区间K大

写了一个多小时…调了大概….一个半小时?

树状数组怎么写都快忘记了……..

由于懒得离散化……所以…..开了一个巨大的数组…….

VJ的内存限制不错….先把数组从400W改到800W…还是RE..怒而改到1.3kW…AC了…..

看了看空间消耗…..160M…..

这告诉我们千万不要忽视离散化的力量!  千万不要忽视常数空间!

但是我还是很懒=w=能不写离散化就不写离散化=w=

好吧……

下面是代码…..

附带一大版的文件头以及调试信息2333

 

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 typedef unsigned int uint;
  18. 18 typedef long long int ll;
  19. 19 typedef unsigned long long int ull;
  20. 20 typedef double db;
  21. 21
  22. 22 using namespace std;
  23. 23
  24. 24 inline int getint()
  25. 25 {
  26. 26 int res=0;
  27. 27 char c=getchar();
  28. 28 bool mi=false;
  29. 29 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  30. 30 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  31. 31 return mi ? -res : res;
  32. 32 }
  33. 33 inline ll getll()
  34. 34 {
  35. 35 ll res=0;
  36. 36 char c=getchar();
  37. 37 bool mi=false;
  38. 38 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  39. 39 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  40. 40 return mi ? -res : res;
  41. 41 }
  42. 42
  43. 43 db eps=1e-18;
  44. 44 inline bool feq(db a,db b)
  45. 45 { return fabs(a-b)<eps; }
  46. 46
  47. 47 inline int avg(const int a,const int b)
  48. 48 { return a+((b-a)>>1); }
  49. 49
  50. 50 //==============================================================================
  51. 51 //==============================================================================
  52. 52 //==============================================================================
  53. 53 //==============================================================================
  54. 54
  55. 55 const int INF=(1<<30)-1;
  56. 56
  57. 57 int n;
  58. 58 struct node*nil;
  59. 59 struct node
  60. 60 {
  61. 61 int v; //total
  62. 62 node*l,*r;
  63. 63 void update()
  64. 64 { v=l->v+r->v; }
  65. 65 }pool[13000000];
  66. 66 node*nt=pool;
  67. 67 node*newnode()
  68. 68 {
  69. 69 nt->l=nt->r=nil;
  70. 70 nt->v=0;
  71. 71 return nt++;
  72. 72 }
  73. 73
  74. 74 int cp,cv;
  75. 75
  76. 76 //Sub segment trees
  77. 77 struct SegmentTree
  78. 78 {
  79. 79 node*root;
  80. 80
  81. 81 node*Change(node*x,int l=0,int r=INF)
  82. 82 {
  83. 83 if(cp<l || r<cp) return x;
  84. 84 if(x==nil) x=newnode();
  85. 85 if(l==r) { x->v+=cv; return x; }
  86. 86 int mid=avg(l,r);
  87. 87 x->l=Change(x->l,l,mid);
  88. 88 x->r=Change(x->r,mid+1,r);
  89. 89 x->update();
  90. 90 return x;
  91. 91 }
  92. 92
  93. 93 void Set(int p,int v)
  94. 94 {
  95. 95 if(root<pool) root=nil;
  96. 96 cp=p;
  97. 97 cv=v;
  98. 98 root=Change(root);
  99. 99 }
  100. 100 };
  101. 101
  102. 102 //original segment tree
  103. 103 //performed as tree array
  104. 104
  105. 105 #define bt(x) (x&-x)
  106. 106
  107. 107 int a[1000000]; //this array must be stay here....
  108. 108 SegmentTree t[1000000];
  109. 109 void Change(int p,int s,int v) //location of point, value of point, delete or add in.
  110. 110 { for(int i=p;i<=n;i+=bt(i)) t[i].Set(s,v); }
  111. 111
  112. 112 node*c[1000];
  113. 113 int adt,ct;
  114. 114
  115. 115 int Query(int l,int r,int k) //find the element which is rank k.
  116. 116 {
  117. 117 adt=0;
  118. 118
  119. 119 for(int i=r;i>0;i-=bt(i))
  120. 120 c[adt++]=t[i].root;
  121. 121
  122. 122 ct=adt;
  123. 123 for(int i=l-1;i>0;i-=bt(i))
  124. 124 c[ct++]=t[i].root;
  125. 125
  126. 126 //we perform add when i<adt, and than dec when adt<=i<ct
  127. 127
  128. 128
  129. 129 l=0,r=INF;
  130. 130 while(l!=r)
  131. 131 {
  132. 132 //for(int i=0;i<ct;i++)
  133. 133 //cout<<c[i]<<\' \'; cout<<endl; cout<<l<<\' \'<<r<<endl; cout<<endl;
  134. 134
  135. 135 int mid=avg(l,r);
  136. 136 int clv=0; //current node\'s left node count.
  137. 137
  138. 138 for(int i=0;i<adt;i++)
  139. 139 clv+=c[i]->l->v;
  140. 140 for(int i=adt;i<ct;i++)
  141. 141 clv-=c[i]->l->v;
  142. 142
  143. 143 if(k<=clv) //the element we want find is on the left block
  144. 144 {
  145. 145 for(int i=0;i<ct;i++)
  146. 146 c[i]=c[i]->l;
  147. 147 r=mid;
  148. 148 }
  149. 149 else
  150. 150 {
  151. 151 for(int i=0;i<ct;i++)
  152. 152 c[i]=c[i]->r;
  153. 153 k-=clv;
  154. 154 l=mid+1;
  155. 155 }
  156. 156 }
  157. 157
  158. 158 return l;
  159. 159 }
  160. 160
  161. 161 int q;
  162. 162
  163. 163 int main()
  164. 164 {
  165. 165 nil=newnode();
  166. 166 nil->l=nil->r=nil;
  167. 167 nil->v=0;
  168. 168
  169. 169 n=getint();
  170. 170 q=getint();
  171. 171 for(int i=0;i<n;i++)
  172. 172 Change(i+1,a[i+1]=getint(),1);
  173. 173
  174. 174 for(int i=0;i<q;i++)
  175. 175 {
  176. 176 char c[5];
  177. 177 scanf("%s",c);
  178. 178 if(c[0]==\'C\')
  179. 179 {
  180. 180 int i=getint();
  181. 181 int v=getint();
  182. 182 Change(i,a[i],-1);
  183. 183 Change(i,a[i]=v,1);
  184. 184 }
  185. 185 else
  186. 186 {
  187. 187 int i=getint();
  188. 188 int j=getint();
  189. 189 int k=getint();
  190. 190 printf("%d\n",Query(i,j,k));
  191. 191 }
  192. 192 }
  193. 193
  194. 194 return 0;
  195. 195 }
  196. 196
  197. 197

View Code

 

需要注意的地方:

1.树状数组什么的一级结构别写错了啊啊啊啊啊啊

2.既然是动态开点(即便离散化了也给我动态!绝对不要写静态的树套在另外的树里面!)….

那么,我们只需要记录每棵树的根节点就好了.其它节点在访问的时候会碰到.

3.嗯….(结构相同的)线段树是可加的…….所以不要再去写二分,直接在加起来的那棵树上隐式二分即可.详见代码.可以降低一个log的复杂度.

4.二分的界,以及二分后的操作(k-=…)一定要考虑清楚.

2015年3月4日更新

<5.不知道为什么, 用@iwtwiioi在某些地方的AC代码交到VJ,TLE了…就AC了我第一次提交没有RE的那两个范围较小的点…… http://www.cnblogs.com/iwtwiioi/p/3929957.html>

嘛,以上TLE的原因是在BZOJ上原题的数据范围是n<=1W,VIJOS上是N<=5W…..噗……不知道当时看走眼了还是什么的囧

 

树状数组套动态开点的权值线段树

AC BZOJ 3196 tyvj 二逼平衡树

传说中都用树状数组套Treap…..然而我是蒟蒻不会套平衡树……所以写了线段树…..1A…..

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 typedef unsigned int uint;
  18. 18 typedef long long int ll;
  19. 19 typedef unsigned long long int ull;
  20. 20 typedef double db;
  21. 21
  22. 22 using namespace std;
  23. 23
  24. 24 inline int getint()
  25. 25 {
  26. 26 int res=0;
  27. 27 char c=getchar();
  28. 28 bool mi=false;
  29. 29 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  30. 30 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  31. 31 return mi ? -res : res;
  32. 32 }
  33. 33 inline ll getll()
  34. 34 {
  35. 35 ll res=0;
  36. 36 char c=getchar();
  37. 37 bool mi=false;
  38. 38 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  39. 39 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  40. 40 return mi ? -res : res;
  41. 41 }
  42. 42
  43. 43 //==============================================================================
  44. 44 //==============================================================================
  45. 45 //==============================================================================
  46. 46 //==============================================================================
  47. 47
  48. 48
  49. 49
  50. 50 const int INF=100000001;
  51. 51
  52. 52
  53. 53 struct node*nil;
  54. 54 struct node
  55. 55 {
  56. 56 int v;
  57. 57 node*l,*r;
  58. 58 };
  59. 59 int ncnt=5000;
  60. 60 node*nt;
  61. 61 node*newnode()
  62. 62 {
  63. 63 if(ncnt==5000) { ncnt=0; nt=new node[5000]; }
  64. 64 nt->l=nt->r=nil;
  65. 65 ncnt++; return nt++;
  66. 66 }
  67. 67
  68. 68 int ip,iv;
  69. 69 void Insert(node*&x,int l=-1,int r=INF)
  70. 70 {
  71. 71 if(ip<l || r<ip) return ;
  72. 72 if(x==nil) x=newnode();
  73. 73 int mid=(l+r)>>1;
  74. 74 if(l==r) { x->v+=iv; return ; }
  75. 75 Insert(x->l,l,mid);
  76. 76 Insert(x->r,mid+1,r);
  77. 77 x->v = x->l->v + x->r->v;
  78. 78 }
  79. 79
  80. 80 int n,m;
  81. 81 int a[50050]; // true array
  82. 82
  83. 83 node*t[50050];
  84. 84 void Change(int loc,int p,int v)
  85. 85 {
  86. 86 ip=p; iv=v;
  87. 87 for(int i=loc;i<=n;i+=(i&-i))
  88. 88 Insert(t[i]);
  89. 89 }
  90. 90
  91. 91 node*p[1000];
  92. 92 node*s[1000];
  93. 93 int sp,ss;
  94. 94 inline void QueryBIT(int L,int R)
  95. 95 {
  96. 96 sp=ss=0;
  97. 97 for(int i=L-1;i;i-=(i&-i)) s[ss++]=t[i];
  98. 98 for(int i=R;i;i-=(i&-i)) p[sp++]=t[i];
  99. 99 }
  100. 100 inline void GoLeft()
  101. 101 {
  102. 102 for(int i=0;i<sp;i++) p[i]=p[i]->l;
  103. 103 for(int i=0;i<ss;i++) s[i]=s[i]->l;
  104. 104 }
  105. 105 inline void GoRight()
  106. 106 {
  107. 107 for(int i=0;i<sp;i++) p[i]=p[i]->r;
  108. 108 for(int i=0;i<ss;i++) s[i]=s[i]->r;
  109. 109 }
  110. 110 inline int CountLeft()
  111. 111 {
  112. 112 int res=0;
  113. 113 for(int i=0;i<sp;i++) res+=p[i]->l->v;
  114. 114 for(int i=0;i<ss;i++) res-=s[i]->l->v;
  115. 115 return res;
  116. 116 }
  117. 117 inline int CountRight()
  118. 118 {
  119. 119 int res=0;
  120. 120 for(int i=0;i<sp;i++) res+=p[i]->r->v;
  121. 121 for(int i=0;i<ss;i++) res-=s[i]->r->v;
  122. 122 return res;
  123. 123 }
  124. 124
  125. 125 int GetRank(int v) //Query the count of numbers smaller than v.
  126. 126 {
  127. 127 int l=-1,r=INF;
  128. 128 int res=0;
  129. 129 while(l!=r)
  130. 130 {
  131. 131 int mid=(l+r)>>1;
  132. 132 if(v<=mid) { GoLeft(); r=mid; }
  133. 133 else { res+=CountLeft(); GoRight(); l=mid+1; }
  134. 134 }
  135. 135 return res;
  136. 136 }
  137. 137
  138. 138 int FindRank(int k) //find the number with rank k.
  139. 139 {
  140. 140 int l=-1,r=INF;
  141. 141 while(l!=r)
  142. 142 {
  143. 143 int mid=(l+r)>>1;
  144. 144 int t=CountLeft();
  145. 145 if(k<=t) { GoLeft(); r=mid; }
  146. 146 else { k-=t; GoRight(); l=mid+1; }
  147. 147 }
  148. 148 return l;
  149. 149 }
  150. 150
  151. 151 int GetPrefix(int L,int R,int v)
  152. 152 {
  153. 153 QueryBIT(L,R);
  154. 154 int t=GetRank(v);
  155. 155 QueryBIT(L,R);
  156. 156 return FindRank(t);
  157. 157 }
  158. 158
  159. 159 int GetSuffix(int L,int R,int v)
  160. 160 {
  161. 161 QueryBIT(L,R);
  162. 162 int t=GetRank(v+1);
  163. 163 QueryBIT(L,R);
  164. 164 return FindRank(t+1);
  165. 165 }
  166. 166
  167. 167 int main()
  168. 168 {
  169. 169 nil=new node;
  170. 170 nil->l=nil->r=nil;
  171. 171 nil->v=0;
  172. 172
  173. 173 n=getint();
  174. 174 m=getint();
  175. 175
  176. 176 for(int i=0;i<=n;i++)
  177. 177 t[i]=nil;
  178. 178
  179. 179 for(int i=1;i<=n;i++)
  180. 180 Change(i,a[i]=getint(),1);
  181. 181
  182. 182 for(int i=0;i<m;i++)
  183. 183 {
  184. 184 int c=getint();
  185. 185 int b=getint();
  186. 186 int d=getint();
  187. 187 if(c==1) //Get Rank
  188. 188 {
  189. 189 int v=getint();
  190. 190 QueryBIT(b,d);
  191. 191 printf("%d\n",GetRank(v)+1);
  192. 192 }
  193. 193 else if(c==2) //Find by Rank
  194. 194 {
  195. 195 int k=getint();
  196. 196 QueryBIT(b,d);
  197. 197 printf("%d\n",FindRank(k));
  198. 198 }
  199. 199 else if(c==3) //Change
  200. 200 {
  201. 201 Change(b,a[b],-1);
  202. 202 Change(b,a[b]=d,1);
  203. 203 }
  204. 204 else if(c==4) //Prefix
  205. 205 {
  206. 206 int v=getint();
  207. 207 printf("%d\n",GetPrefix(b,d,v));
  208. 208 }
  209. 209 else if(c==5) //Suffix
  210. 210 {
  211. 211 int v=getint();
  212. 212 printf("%d\n",GetSuffix(b,d,v));
  213. 213 }
  214. 214 }
  215. 215
  216. 216 return 0;
  217. 217 }

View Code

运行时间为3.46s. 这个找前驱和后继的操作简直SXBK……

先统计一下比那个数小的数的个数(就是找排名)……然后再找到排名等于那个数的数……后继差不多…..

似乎比较慢? 没有开离散化….内存用得很多…..但是比treap快2333333

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 typedef unsigned int uint;
  18. 18 typedef long long int ll;
  19. 19 typedef unsigned long long int ull;
  20. 20 typedef double db;
  21. 21
  22. 22 using namespace std;
  23. 23
  24. 24 inline int getint()
  25. 25 {
  26. 26 int res=0;
  27. 27 char c=getchar();
  28. 28 bool mi=false;
  29. 29 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  30. 30 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  31. 31 return mi ? -res : res;
  32. 32 }
  33. 33 inline ll getll()
  34. 34 {
  35. 35 ll res=0;
  36. 36 char c=getchar();
  37. 37 bool mi=false;
  38. 38 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  39. 39 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  40. 40 return mi ? -res : res;
  41. 41 }
  42. 42
  43. 43 //==============================================================================
  44. 44 //==============================================================================
  45. 45 //==============================================================================
  46. 46 //==============================================================================
  47. 47
  48. 48
  49. 49 struct node*nil;
  50. 50 struct node
  51. 51 {
  52. 52 int v;
  53. 53 node*l,*r;
  54. 54 };
  55. 55 int ncnt=5000;
  56. 56 node*nt;
  57. 57 node*newnode()
  58. 58 {
  59. 59 if(ncnt==5000) { ncnt=0; nt=new node[5000]; }
  60. 60 nt->l=nt->r=nil;
  61. 61 ncnt++; return nt++;
  62. 62 }
  63. 63
  64. 64 int lim;
  65. 65
  66. 66 int ip,iv;
  67. 67 void Insert(node*&x,int l=0,int r=lim-1)
  68. 68 {
  69. 69 if(ip<l || r<ip) return ;
  70. 70 if(x==nil) x=newnode();
  71. 71 int mid=(l+r)>>1;
  72. 72 if(l==r) { x->v+=iv; return ; }
  73. 73 Insert(x->l,l,mid);
  74. 74 Insert(x->r,mid+1,r);
  75. 75 x->v = x->l->v + x->r->v;
  76. 76 }
  77. 77
  78. 78 int n,m;
  79. 79 int a[50050]; // true array
  80. 80
  81. 81 node*t[50050];
  82. 82 void Change(int loc,int p,int v)
  83. 83 {
  84. 84 ip=p; iv=v;
  85. 85 for(int i=loc;i<=n;i+=(i&-i))
  86. 86 Insert(t[i]);
  87. 87 }
  88. 88
  89. 89 node*p[1000];
  90. 90 node*s[1000];
  91. 91 int sp,ss;
  92. 92 inline void QueryBIT(int L,int R)
  93. 93 {
  94. 94 sp=ss=0;
  95. 95 for(int i=L-1;i;i-=(i&-i)) s[ss++]=t[i];
  96. 96 for(int i=R;i;i-=(i&-i)) p[sp++]=t[i];
  97. 97 }
  98. 98 inline void GoLeft()
  99. 99 {
  100. 100 for(int i=0;i<sp;i++) p[i]=p[i]->l;
  101. 101 for(int i=0;i<ss;i++) s[i]=s[i]->l;
  102. 102 }
  103. 103 inline void GoRight()
  104. 104 {
  105. 105 for(int i=0;i<sp;i++) p[i]=p[i]->r;
  106. 106 for(int i=0;i<ss;i++) s[i]=s[i]->r;
  107. 107 }
  108. 108 inline int CountLeft()
  109. 109 {
  110. 110 int res=0;
  111. 111 for(int i=0;i<sp;i++) res+=p[i]->l->v;
  112. 112 for(int i=0;i<ss;i++) res-=s[i]->l->v;
  113. 113 return res;
  114. 114 }
  115. 115 inline int CountRight()
  116. 116 {
  117. 117 int res=0;
  118. 118 for(int i=0;i<sp;i++) res+=p[i]->r->v;
  119. 119 for(int i=0;i<ss;i++) res-=s[i]->r->v;
  120. 120 return res;
  121. 121 }
  122. 122
  123. 123 int GetRank(int v) //Query the count of numbers smaller than v.
  124. 124 {
  125. 125 int l=0,r=lim-1;
  126. 126 int res=0;
  127. 127 while(l!=r)
  128. 128 {
  129. 129 int mid=(l+r)>>1;
  130. 130 if(v<=mid) { GoLeft(); r=mid; }
  131. 131 else { res+=CountLeft(); GoRight(); l=mid+1; }
  132. 132 }
  133. 133 return res;
  134. 134 }
  135. 135
  136. 136 int FindRank(int k) //find the number with rank k.
  137. 137 {
  138. 138 int l=0,r=lim-1;
  139. 139 while(l!=r)
  140. 140 {
  141. 141 int mid=(l+r)>>1;
  142. 142 int t=CountLeft();
  143. 143 if(k<=t) { GoLeft(); r=mid; }
  144. 144 else { k-=t; GoRight(); l=mid+1; }
  145. 145 }
  146. 146 return l;
  147. 147 }
  148. 148
  149. 149 int GetPrefix(int L,int R,int v)
  150. 150 {
  151. 151 QueryBIT(L,R);
  152. 152 int t=GetRank(v);
  153. 153 QueryBIT(L,R);
  154. 154 return FindRank(t);
  155. 155 }
  156. 156
  157. 157 int GetSuffix(int L,int R,int v)
  158. 158 {
  159. 159 QueryBIT(L,R);
  160. 160 int t=GetRank(v+1);
  161. 161 QueryBIT(L,R);
  162. 162 return FindRank(t+1);
  163. 163 }
  164. 164
  165. 165 int op[50050][4];
  166. 166 int v[105000];
  167. 167 int c;
  168. 168
  169. 169 int main()
  170. 170 {
  171. 171 nil=new node;
  172. 172 nil->l=nil->r=nil;
  173. 173 nil->v=0;
  174. 174
  175. 175 n=getint();
  176. 176 m=getint();
  177. 177
  178. 178 for(int i=0;i<=n;i++)
  179. 179 t[i]=nil;
  180. 180
  181. 181 for(int i=1;i<=n;i++)
  182. 182 v[c++]=a[i]=getint();
  183. 183
  184. 184 for(int i=0;i<m;i++)
  185. 185 {
  186. 186 op[i][0]=getint();
  187. 187 op[i][1]=getint();
  188. 188 op[i][2]=getint();
  189. 189 if(op[i][0]!=3) op[i][3]=getint();
  190. 190
  191. 191 if(op[i][0]==3) v[c++]=op[i][2];
  192. 192 else
  193. 193 if(op[i][0]!=2) v[c++]=op[i][3];
  194. 194 }
  195. 195
  196. 196 sort(v,v+c);
  197. 197 lim=int(unique(v,v+c)-v);
  198. 198 for(int i=1;i<=n;i++)
  199. 199 a[i]=int(lower_bound(v,v+lim,a[i])-v);
  200. 200 for(int i=0;i<m;i++)
  201. 201 if(op[i][0]==3) op[i][2]=int(lower_bound(v,v+lim,op[i][2])-v);
  202. 202 else
  203. 203 if(op[i][0]!=2) op[i][3]=int(lower_bound(v,v+lim,op[i][3])-v);
  204. 204
  205. 205 for(int i=1;i<=n;i++)
  206. 206 Change(i,a[i],1);
  207. 207
  208. 208 for(int i=0;i<m;i++)
  209. 209 {
  210. 210 //printf("i:%d ",i);
  211. 211 if(op[i][0]==1) //Get Rank
  212. 212 {
  213. 213 QueryBIT(op[i][1],op[i][2]);
  214. 214 printf("%d\n",GetRank(op[i][3])+1);
  215. 215 }
  216. 216 else if(op[i][0]==2) //Find by Rank
  217. 217 {
  218. 218 QueryBIT(op[i][1],op[i][2]);
  219. 219 printf("%d\n",v[FindRank(op[i][3])]);
  220. 220 }
  221. 221 else if(op[i][0]==3) //Change
  222. 222 {
  223. 223 Change(op[i][1],a[op[i][1]],-1);
  224. 224 Change(op[i][1],a[op[i][1]]=op[i][2],1);
  225. 225 }
  226. 226 else if(op[i][0]==4) //Prefix
  227. 227 printf("%d\n",v[GetPrefix(op[i][1],op[i][2],op[i][3])]);
  228. 228 else if(op[i][0]==5) //Suffix
  229. 229 printf("%d\n",v[GetSuffix(op[i][1],op[i][2],op[i][3])]);
  230. 230 }
  231. 231
  232. 232 return 0;
  233. 233 }

View Code

加离散化之后2.37s….内存少了50M…..

 

AC BZOJ 3110

权值线段树套常规线段树

 

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 typedef unsigned int uint;
  18. 18 typedef long long int ll;
  19. 19 typedef unsigned long long int ull;
  20. 20 typedef double db;
  21. 21 typedef long double ldb;
  22. 22
  23. 23 using namespace std;
  24. 24
  25. 25 inline int getint()
  26. 26 {
  27. 27 int res=0;
  28. 28 char c=getchar();
  29. 29 bool mi=false;
  30. 30 while((c<\'0\' || c>\'9\')/* && !feof(stdin)*/) mi=(c==\'-\'),c=getchar();
  31. 31 while(\'0\'<=c && c<=\'9\'/* && !feof(stdin)*/) res=res*10+c-\'0\',c=getchar();
  32. 32 return mi ? -res : res;
  33. 33 }
  34. 34 inline ll getll()
  35. 35 {
  36. 36 ll res=0;
  37. 37 char c=getchar();
  38. 38 bool mi=false;
  39. 39 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  40. 40 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  41. 41 return mi ? -res : res;
  42. 42 }
  43. 43
  44. 44 //==============================================================================
  45. 45 //==============================================================================
  46. 46 //==============================================================================
  47. 47 //==============================================================================
  48. 48
  49. 49
  50. 50 struct operation{bool t; int l,r; int v; }op[50050];
  51. 51 int dsv[50050]; int vt;
  52. 52
  53. 53 //segment tree
  54. 54 struct node{ node*l,*r; int t; int tag; };
  55. 55 node*nt; int ncnt=20000;
  56. 56 node*newnode()
  57. 57 {
  58. 58 if(ncnt==20000){ nt=new node[20000]; ncnt=0; }
  59. 59 nt->l=nt->r=NULL; nt->t=nt->tag=0; ncnt++;
  60. 60 return nt++;
  61. 61 }
  62. 62
  63. 63 int n,m;
  64. 64
  65. 65 int cl,cr;
  66. 66 void Change(node*&x,int l=0,int r=n-1)
  67. 67 {
  68. 68 if(x==NULL) x=newnode();
  69. 69 if(cl<=l && r<=cr) { x->tag++; return ; }
  70. 70 int mid=(l+r)>>1;
  71. 71 if(mid>=cl) Change(x->l,l,mid);
  72. 72 if(mid<cr) Change(x->r,mid+1,r);
  73. 73 x->t = ( x->l ? x->l->t + x->l->tag*(mid-l+1) : 0 ) +
  74. 74 ( x->r ? x->r->t + x->r->tag*(r-mid) : 0 ) ;
  75. 75 }
  76. 76 int ql,qr;
  77. 77 int Query(node*x,int l=0,int r=n-1)
  78. 78 {
  79. 79 if(qr<l || r<ql || x==NULL) return 0;
  80. 80 if(ql<=l && r<=qr) { return x->t + x->tag*(r-l+1); }
  81. 81 int mid=(l+r)>>1;
  82. 82 return Query(x->l,l,mid)+Query(x->r,mid+1,r)+x->tag*(min(qr,r)-max(ql,l)+1) ;
  83. 83 }
  84. 84
  85. 85 node*t[205000]; //outer segment tree
  86. 86
  87. 87 void Insert(int L,int R,int p,int x=1,int l=0,int r=vt-1)
  88. 88 {
  89. 89 cl=L; cr=R;
  90. 90 while(l!=r)
  91. 91 {
  92. 92 int mid=(l+r)>>1;
  93. 93 Change(t[x]);
  94. 94 if(p<=mid) { x<<=1; r=mid; }
  95. 95 else { x=x<<1|1; l=mid+1; }
  96. 96 }
  97. 97 Change(t[x]);
  98. 98 }
  99. 99
  100. 100 int Query(int L,int R,int k,int x=1,int l=0,int r=vt-1)
  101. 101 {
  102. 102 ql=L; qr=R;
  103. 103 while(l!=r)
  104. 104 {
  105. 105 int mid=(l+r)>>1;
  106. 106 int v=Query(t[x<<1|1]);
  107. 107 if(k>v) { k-=v; x<<=1; r=mid; }
  108. 108 else { x=x<<1|1; l=mid+1; }
  109. 109 }
  110. 110 return l;
  111. 111 }
  112. 112
  113. 113 int main()
  114. 114 {
  115. 115 n=getint();
  116. 116 m=getint();
  117. 117
  118. 118 for(int i=0;i<m;i++)
  119. 119 {
  120. 120 op[i].t=getint()-1;
  121. 121 op[i].l=getint()-1;
  122. 122 op[i].r=getint()-1;
  123. 123 op[i].v=getint();
  124. 124 if(!op[i].t) dsv[vt++]=op[i].v;
  125. 125 }
  126. 126 sort(dsv,dsv+vt);
  127. 127 vt=int(unique(dsv,dsv+vt)-dsv);
  128. 128 for(int i=0;i<m;i++) if(!op[i].t)
  129. 129 { op[i].v=int(lower_bound(dsv,dsv+vt,op[i].v)-dsv); }
  130. 130
  131. 131 for(int i=0;i<m;i++)
  132. 132 {
  133. 133 if(op[i].t) printf("%d\n",dsv[Query(op[i].l,op[i].r,op[i].v)]);
  134. 134 else Insert(op[i].l,op[i].r,op[i].v);
  135. 135 }
  136. 136
  137. 137 return 0;
  138. 138 }

View Code

居然能这么玩..好神……

我们不是要对每个询问在权值线段树上跑嘛…那么位置限制[l,r]怎么办呢? 树套树! 每一个权值线段树的节点都开一棵线段树,用于统计该节点代表的所有权值在某个区间[l,r]内出现过几次…..好神好神…..

 

 

 

 


动态树

不带其余任何标记的,带换根的LCT.

AC BZOJ2049 一道非常裸的LCT.

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 typedef unsigned int uint;
  18. 18 typedef long long int ll;
  19. 19 typedef unsigned long long int ull;
  20. 20 typedef double db;
  21. 21
  22. 22 using namespace std;
  23. 23
  24. 24 inline int getint()
  25. 25 {
  26. 26 int res=0;
  27. 27 char c=getchar();
  28. 28 bool mi=false;
  29. 29 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  30. 30 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  31. 31 return mi ? -res : res;
  32. 32 }
  33. 33 inline ll getll()
  34. 34 {
  35. 35 ll res=0;
  36. 36 char c=getchar();
  37. 37 bool mi=false;
  38. 38 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  39. 39 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  40. 40 return mi ? -res : res;
  41. 41 }
  42. 42
  43. 43 db eps=1e-18;
  44. 44 inline bool feq(db a,db b)
  45. 45 { return fabs(a-b)<eps; }
  46. 46
  47. 47 template<typename Type>
  48. 48 inline Type avg(const Type a,const Type b)
  49. 49 { return a+((b-a)/2); }
  50. 50
  51. 51 //==============================================================================
  52. 52 //==============================================================================
  53. 53 //==============================================================================
  54. 54 //==============================================================================
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60 struct node* nil;
  61. 61
  62. 62 struct node
  63. 63 {
  64. 64 bool rev;
  65. 65 node*s[2],*f;
  66. 66
  67. 67 bool root()
  68. 68 { return this!=f->s[0] && this!=f->s[1]; }
  69. 69
  70. 70 void pushtag()
  71. 71 {
  72. 72 if(rev)
  73. 73 {
  74. 74 s[0]->rev^=1;
  75. 75 s[1]->rev^=1;
  76. 76 swap(s[0],s[1]);
  77. 77 rev=false;
  78. 78 }
  79. 79 }
  80. 80
  81. 81 };
  82. 82
  83. 83
  84. 84 struct LinkCutTree
  85. 85 {
  86. 86 node*nt;
  87. 87 LinkCutTree(int size)
  88. 88 {
  89. 89 nt=new node[size];
  90. 90 for(int i=0;i<size;i++)
  91. 91 {
  92. 92 nt[i].s[0]=nt[i].s[1]=nt[i].f=nil;
  93. 93 nt[i].rev=false;
  94. 94 }
  95. 95 }
  96. 96
  97. 97 void cleartag(node*x)
  98. 98 { if(!x->root()) cleartag(x->f); x->pushtag(); }
  99. 99
  100. 100 node*operator[](int k)
  101. 101 { return nt+k; }
  102. 102
  103. 103 void rot(node*x)
  104. 104 {
  105. 105 if(x->root()) return ;
  106. 106 node*y=x->f;
  107. 107 bool k=(x==y->s[0]);
  108. 108
  109. 109 y->s[!k]=x->s[k];
  110. 110 if(x->s[k]!=nil) x->s[k]->f=y;
  111. 111
  112. 112 x->f=y->f;
  113. 113 if(y==y->f->s[0]) y->f->s[0]=x;
  114. 114 else if(y==y->f->s[1]) y->f->s[1]=x;
  115. 115
  116. 116 y->f=x;
  117. 117 x->s[k]=y;
  118. 118 }
  119. 119
  120. 120 void splay(node*x)
  121. 121 {
  122. 122 cleartag(x);
  123. 123 while(!x->root())
  124. 124 {
  125. 125 node*y=x->f;
  126. 126 if(!y->root())
  127. 127 {
  128. 128 if((x==y->s[0])^(y==y->f->s[0]))
  129. 129 rot(y); else rot(x);
  130. 130 }
  131. 131 rot(x);
  132. 132 }
  133. 133 }
  134. 134
  135. 135 node*access(node*x)
  136. 136 {
  137. 137 node*y=nil;
  138. 138 node*t=x;
  139. 139 while(t!=nil)
  140. 140 {
  141. 141 splay(t);
  142. 142 t->s[0]=y;
  143. 143 y=t;
  144. 144 t=t->f;
  145. 145 }
  146. 146 splay(x);
  147. 147 return x;
  148. 148 }
  149. 149
  150. 150 node*FindRoot(node*x)
  151. 151 {
  152. 152 access(x);
  153. 153 while(x->s[1]!=nil) x=x->s[1];
  154. 154 return x;
  155. 155 }
  156. 156
  157. 157 node*SetRoot(node*x)
  158. 158 {
  159. 159 access(x)->rev^=1;
  160. 160 return x;
  161. 161 }
  162. 162
  163. 163 void Link(node*x,node*y)
  164. 164 {
  165. 165 SetRoot(x)->f=y;
  166. 166 }
  167. 167
  168. 168 void Cut(node*x,node*y)
  169. 169 {
  170. 170 SetRoot(x);
  171. 171 access(y);
  172. 172 y->s[1]->f=nil;
  173. 173 y->s[1]=nil;
  174. 174 }
  175. 175
  176. 176 void output(int i)
  177. 177 { cout<<i<<\' \'<<&nt[i]<<\' \'<<nt[i].s[0]<<\' \'<<nt[i].s[1]<<\' \'<<nt[i].f<<endl; }
  178. 178 };
  179. 179
  180. 180 int n,m;
  181. 181
  182. 182 int main()
  183. 183 {
  184. 184 nil=new node;
  185. 185 nil->s[0]=nil->s[1]=nil->f=nil;
  186. 186
  187. 187 n=getint();
  188. 188 m=getint();
  189. 189
  190. 190 LinkCutTree t(n);
  191. 191
  192. 192 for(int i=0;i<m;i++)
  193. 193 {
  194. 194 char c[20];
  195. 195 scanf("%s",c);
  196. 196 if(c[0]==\'C\') //Link
  197. 197 {
  198. 198 t.Link(t[getint()-1],t[getint()-1]);
  199. 199 }
  200. 200 else if(c[0]==\'D\') //Cut
  201. 201 {
  202. 202 t.Cut(t[getint()-1],t[getint()-1]);
  203. 203 }
  204. 204 else if(c[0]==\'Q\') //Query
  205. 205 {
  206. 206 if(t.FindRoot(t[getint()-1])==t.FindRoot(t[getint()-1])) printf("Yes\n");
  207. 207 else printf("No\n");
  208. 208 }
  209. 209 }
  210. 210
  211. 211 return 0;
  212. 212 }

View Code

 

很奇怪,Link,Cut,FindRoot和SetRoot这些函数换一种写法就各种TLE/RE,还有cleartag()也是一样,不知道为什么…..

 

还是LCT.

AC VIJOS1190 LCT-MST

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 typedef unsigned int uint;
  18. 18 typedef long long int ll;
  19. 19 typedef unsigned long long int ull;
  20. 20 typedef double db;
  21. 21
  22. 22 using namespace std;
  23. 23
  24. 24 inline int getint()
  25. 25 {
  26. 26 int res=0;
  27. 27 char c=getchar();
  28. 28 bool mi=false;
  29. 29 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  30. 30 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  31. 31 return mi ? -res : res;
  32. 32 }
  33. 33 inline ll getll()
  34. 34 {
  35. 35 ll res=0;
  36. 36 char c=getchar();
  37. 37 bool mi=false;
  38. 38 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  39. 39 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  40. 40 return mi ? -res : res;
  41. 41 }
  42. 42
  43. 43 db eps=1e-18;
  44. 44 inline bool feq(db a,db b)
  45. 45 { return fabs(a-b)<eps; }
  46. 46
  47. 47 template<typename Type>
  48. 48 inline Type avg(const Type a,const Type b)
  49. 49 { return a+((b-a)/2); }
  50. 50
  51. 51 //==============================================================================
  52. 52 //==============================================================================
  53. 53 //==============================================================================
  54. 54 //==============================================================================
  55. 55
  56. 56
  57. 57 const int INF=(1<<30)-1;
  58. 58
  59. 59
  60. 60 struct node* nil;
  61. 61
  62. 62 struct node
  63. 63 {
  64. 64 node*mxp;
  65. 65 int code;
  66. 66 int v;
  67. 67 bool rev;
  68. 68 node*s[2],*f;
  69. 69
  70. 70 bool root()
  71. 71 { return this!=f->s[0] && this!=f->s[1]; }
  72. 72
  73. 73 void pushtag()
  74. 74 {
  75. 75 if(rev)
  76. 76 {
  77. 77 s[0]->rev^=1;
  78. 78 s[1]->rev^=1;
  79. 79 swap(s[0],s[1]);
  80. 80 rev=false;
  81. 81 }
  82. 82 }
  83. 83
  84. 84 void update()
  85. 85 {
  86. 86 mxp=this;
  87. 87 int lv=s[0]->mxp->v;
  88. 88 int rv=s[1]->mxp->v;
  89. 89 if(lv>mxp->v) mxp=s[0]->mxp;
  90. 90 if(rv>mxp->v) mxp=s[1]->mxp;
  91. 91 }
  92. 92 };
  93. 93
  94. 94
  95. 95 struct LinkCutTree
  96. 96 {
  97. 97 node*nt;
  98. 98 LinkCutTree(int size)
  99. 99 {
  100. 100 nt=new node[size];
  101. 101 for(int i=0;i<size;i++)
  102. 102 {
  103. 103 nt[i].s[0]=nt[i].s[1]=nt[i].f=nil;
  104. 104 nt[i].rev=false;
  105. 105 nt[i].mxp=&nt[i];
  106. 106 nt[i].v=-INF;
  107. 107 nt[i].code=i;
  108. 108 }
  109. 109 }
  110. 110
  111. 111 void cleartag(node*x)
  112. 112 { if(!x->root()) cleartag(x->f); x->pushtag(); }
  113. 113
  114. 114 node*operator[](int k)
  115. 115 { return nt+k; }
  116. 116
  117. 117 void rot(node*x)
  118. 118 {
  119. 119 if(x->root()) return ;
  120. 120 node*y=x->f;
  121. 121 bool k=(x==y->s[0]);
  122. 122
  123. 123 y->s[!k]=x->s[k];
  124. 124 if(x->s[k]!=nil) x->s[k]->f=y;
  125. 125
  126. 126 x->f=y->f;
  127. 127 if(y==y->f->s[0]) y->f->s[0]=x;
  128. 128 else if(y==y->f->s[1]) y->f->s[1]=x;
  129. 129
  130. 130 y->f=x;
  131. 131 x->s[k]=y;
  132. 132
  133. 133 y->update();
  134. 134 }
  135. 135
  136. 136 void splay(node*x)
  137. 137 {
  138. 138 cleartag(x);
  139. 139 while(!x->root())
  140. 140 {
  141. 141 node*y=x->f;
  142. 142 if(!y->root())
  143. 143 {
  144. 144 if((x==y->s[0])^(y==y->f->s[0]))
  145. 145 rot(y); else rot(x);
  146. 146 }
  147. 147 rot(x);
  148. 148 }
  149. 149 x->update();
  150. 150 }
  151. 151
  152. 152 node*access(node*x)
  153. 153 {
  154. 154 node*y=nil;
  155. 155 while(x!=nil)
  156. 156 {
  157. 157 splay(x);
  158. 158 x->s[0]=y;
  159. 159 y=x;
  160. 160 x=x->f;
  161. 161 }
  162. 162 return x;
  163. 163 }
  164. 164
  165. 165 node*expend(node*x)
  166. 166 {
  167. 167 access(x);
  168. 168 splay(x);
  169. 169 return x;
  170. 170 }
  171. 171
  172. 172 node*FindRoot(node*x)
  173. 173 {
  174. 174 expend(x);
  175. 175 while(x->s[1]!=nil) x=x->s[1];
  176. 176 splay(x);
  177. 177 return x;
  178. 178 }
  179. 179
  180. 180 node*SetRoot(node*x)
  181. 181 {
  182. 182 expend(x)->rev^=1;
  183. 183 return x;
  184. 184 }
  185. 185
  186. 186 void Link(node*x,node*y)
  187. 187 {
  188. 188 SetRoot(x)->f=y;
  189. 189 }
  190. 190
  191. 191 void Cut(node*x,node*y)
  192. 192 {
  193. 193 SetRoot(x);
  194. 194 expend(y);
  195. 195 y->s[1]->f=nil;
  196. 196 y->s[1]=nil;
  197. 197 }
  198. 198
  199. 199 node* GetMax(node*x,node*y)
  200. 200 {
  201. 201 SetRoot(x);
  202. 202 return expend(y)->mxp;
  203. 203 }
  204. 204
  205. 205
  206. 206 void output(int i)
  207. 207 { printf("%p[ id:%d v:%d L:%p R:%p f:%p rev:%d max:%d ]\n",&nt[i],nt[i].code,nt[i].v,nt[i].s[0],nt[i].s[1],nt[i].f,nt[i].rev,nt[i].mxp->v); }
  208. 208 };
  209. 209
  210. 210 int n,m;
  211. 211 int EL[10050];
  212. 212 int ER[10050];
  213. 213
  214. 214 int main()
  215. 215 {
  216. 216 nil=new node;
  217. 217 nil->mxp=nil->s[0]=nil->s[1]=nil->f=nil;
  218. 218 nil->v=-INF;
  219. 219 nil->code=-1;
  220. 220
  221. 221 n=getint();
  222. 222 m=getint();
  223. 223
  224. 224 LinkCutTree T(n+m+1);
  225. 225
  226. 226 int mx=-INF;
  227. 227
  228. 228 for(int i=0;i<m;i++)
  229. 229 {
  230. 230 int p=n+i;
  231. 231
  232. 232 int a,b,c;
  233. 233 EL[i]=(a=getint()-1);
  234. 234 ER[i]=(b=getint()-1);
  235. 235 c=getint();
  236. 236
  237. 237 T[p]->v=c;
  238. 238
  239. 239 bool able=true;
  240. 240
  241. 241 if(T.FindRoot(T[a])==T.FindRoot(T[b]))
  242. 242 {
  243. 243 node* mxp=T.GetMax(T[a],T[b]);
  244. 244 able=false;
  245. 245
  246. 246 if(mxp->v>c)
  247. 247 {
  248. 248 int d=mxp->code-n;
  249. 249
  250. 250 T.Cut(T[EL[d]],mxp);
  251. 251 T.Cut(T[ER[d]],mxp);
  252. 252
  253. 253 able=true;
  254. 254 }
  255. 255 }
  256. 256
  257. 257 if(able)
  258. 258 {
  259. 259 T.Link(T[a],T[p]);
  260. 260 T.Link(T[b],T[p]);
  261. 261 }
  262. 262 }
  263. 263
  264. 264 for(int i=n;i<n+m;i++)
  265. 265 if(T.FindRoot(T[0])==T.FindRoot(T[i]))
  266. 266 mx=max(mx,T[i]->v);
  267. 267
  268. 268 printf("%d %d\n",n-1,mx);
  269. 269
  270. 270 return 0;
  271. 271 }

View Code

调半天发现update写错了……TAT

 要点:

1.所有的操作函数都不要写错啊!虽然很短……

2.access操作返回的是上一次access时的路径与本次access节点在有根树的LCA.

   所以用expend函数来作为返回x的access操作.

3.找到根后别忘记splay根上去,毕竟访问了根节点就要保证其复杂度.

4.Cut操作一定要换根,expend(y)之后,把y与y的右儿子断掉.尤其是x,y不一定相邻的时候.

5.update()与pushtag()别写错!

6.在splay前把要splay的节点的父节点的tag清空.因为splay操作是以结构作为基础的.

7.不要在写LCT的时候纠结struct node到底该写哪怎么写的问题!想到怎么写就怎么写,并且LCT函数全部用node*形式.

 

NOI2014 Day1 T2 魔法森林 用LCT维护MST.上一题就是为这个做准备的.

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 typedef unsigned int uint;
  18. 18 typedef long long int ll;
  19. 19 typedef unsigned long long int ull;
  20. 20 typedef double db;
  21. 21
  22. 22 using namespace std;
  23. 23
  24. 24 inline int getint()
  25. 25 {
  26. 26 int res=0;
  27. 27 char c=getchar();
  28. 28 bool mi=false;
  29. 29 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  30. 30 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  31. 31 return mi ? -res : res;
  32. 32 }
  33. 33 inline ll getll()
  34. 34 {
  35. 35 ll res=0;
  36. 36 char c=getchar();
  37. 37 bool mi=false;
  38. 38 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  39. 39 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  40. 40 return mi ? -res : res;
  41. 41 }
  42. 42
  43. 43 db eps=1e-18;
  44. 44 inline bool feq(db a,db b)
  45. 45 { return fabs(a-b)<eps; }
  46. 46
  47. 47 template<typename Type>
  48. 48 inline Type avg(const Type a,const Type b)
  49. 49 { return a+((b-a)/2); }
  50. 50
  51. 51 //==============================================================================
  52. 52 //==============================================================================
  53. 53 //==============================================================================
  54. 54 //==============================================================================
  55. 55
  56. 56
  57. 57 const int INF=(1<<30)-1;
  58. 58
  59. 59
  60. 60 struct node* nil;
  61. 61
  62. 62 struct node
  63. 63 {
  64. 64 node*mxp;
  65. 65 int code;
  66. 66 int v;
  67. 67 bool rev;
  68. 68 node*s[2],*f;
  69. 69
  70. 70 bool root()
  71. 71 { return this!=f->s[0] && this!=f->s[1]; }
  72. 72
  73. 73 void pushtag()
  74. 74 {
  75. 75 if(rev)
  76. 76 {
  77. 77 s[0]->rev^=1;
  78. 78 s[1]->rev^=1;
  79. 79 swap(s[0],s[1]);
  80. 80 rev=false;
  81. 81 }
  82. 82 }
  83. 83
  84. 84 void update()
  85. 85 {
  86. 86 mxp=this;
  87. 87 int lv=s[0]->mxp->v;
  88. 88 int rv=s[1]->mxp->v;
  89. 89 if(lv>mxp->v) mxp=s[0]->mxp;
  90. 90 if(rv>mxp->v) mxp=s[1]->mxp;
  91. 91 }
  92. 92 };
  93. 93
  94. 94
  95. 95 struct LinkCutTree
  96. 96 {
  97. 97 node*nt;
  98. 98 LinkCutTree(int size)
  99. 99 {
  100. 100 nt=new node[size];
  101. 101 for(int i=0;i<size;i++)
  102. 102 {
  103. 103 nt[i].s[0]=nt[i].s[1]=nt[i].f=nil;
  104. 104 nt[i].rev=false;
  105. 105 nt[i].mxp=&nt[i];
  106. 106 nt[i].v=-INF;
  107. 107 nt[i].code=i;
  108. 108 }
  109. 109 }
  110. 110
  111. 111 void cleartag(node*x)
  112. 112 { if(!x->root()) cleartag(x->f); x->pushtag(); }
  113. 113
  114. 114 node*operator[](int k)
  115. 115 { return nt+k; }
  116. 116
  117. 117 void rot(node*x)
  118. 118 {
  119. 119 if(x->root()) return ;
  120. 120 node*y=x->f;
  121. 121 bool k=(x==y->s[0]);
  122. 122
  123. 123 y->s[!k]=x->s[k];
  124. 124 if(x->s[k]!=nil) x->s[k]->f=y;
  125. 125
  126. 126 x->f=y->f;
  127. 127 if(y==y->f->s[0]) y->f->s[0]=x;
  128. 128 else if(y==y->f->s[1]) y->f->s[1]=x;
  129. 129
  130. 130 y->f=x;
  131. 131 x->s[k]=y;
  132. 132
  133. 133 y->update();
  134. 134 }
  135. 135
  136. 136 void splay(node*x)
  137. 137 {
  138. 138 cleartag(x);
  139. 139 while(!x->root())
  140. 140 {
  141. 141 node*y=x->f;
  142. 142 if(!y->root())
  143. 143 {
  144. 144 if((x==y->s[0])^(y==y->f->s[0]))
  145. 145 rot(y); else rot(x);
  146. 146 }
  147. 147 rot(x);
  148. 148 }
  149. 149 x->update();
  150. 150 }
  151. 151
  152. 152 node*access(node*x)
  153. 153 {
  154. 154 node*y=nil;
  155. 155 while(x!=nil)
  156. 156 {
  157. 157 splay(x);
  158. 158 x->s[0]=y;
  159. 159 y=x;
  160. 160 x=x->f;
  161. 161 }
  162. 162 return x;
  163. 163 }
  164. 164
  165. 165 node*expend(node*x)
  166. 166 {
  167. 167 access(x);
  168. 168 splay(x);
  169. 169 return x;
  170. 170 }
  171. 171
  172. 172 node*FindRoot(node*x)
  173. 173 {
  174. 174 expend(x);
  175. 175 while(x->s[1]!=nil) x=x->s[1];
  176. 176 splay(x);
  177. 177 return x;
  178. 178 }
  179. 179
  180. 180 node*SetRoot(node*x)
  181. 181 {
  182. 182 expend(x)->rev^=1;
  183. 183 return x;
  184. 184 }
  185. 185
  186. 186 void Link(node*x,node*y)
  187. 187 {
  188. 188 SetRoot(x)->f=y;
  189. 189 }
  190. 190
  191. 191 void Cut(node*x,node*y)
  192. 192 {
  193. 193 SetRoot(x);
  194. 194 expend(y);
  195. 195 y->s[1]->f=nil;
  196. 196 y->s[1]=nil;
  197. 197 }
  198. 198
  199. 199 node* GetMax(node*x,node*y)
  200. 200 {
  201. 201 SetRoot(x);
  202. 202 return expend(y)->mxp;
  203. 203 }
  204. 204
  205. 205
  206. 206 void output(int i)
  207. 207 { printf("%p[ id:%d v:%d L:%p R:%p f:%p rev:%d max:%d ]\n",&nt[i],nt[i].code,nt[i].v,nt[i].s[0],nt[i].s[1],nt[i].f,nt[i].rev,nt[i].mxp->v); }
  208. 208 };
  209. 209
  210. 210 int n,m;
  211. 211 int EL[100050];
  212. 212 int ER[100050];
  213. 213 int Ea[100050];
  214. 214 int Eb[100050];
  215. 215 int p[100050];
  216. 216 bool cmp(int a,int b)
  217. 217 { return Ea[a]<Ea[b]; }
  218. 218
  219. 219 int res=INF;
  220. 220
  221. 221 int main()
  222. 222 {
  223. 223 nil=new node;
  224. 224 nil->mxp=nil->s[0]=nil->s[1]=nil->f=nil;
  225. 225 nil->v=-INF;
  226. 226 nil->code=-1;
  227. 227
  228. 228 n=getint();
  229. 229 m=getint();
  230. 230
  231. 231 LinkCutTree T(n+m+2);
  232. 232
  233. 233 int st=0,ed=n-1;
  234. 234
  235. 235 for(int i=0;i<m;i++)
  236. 236 {
  237. 237 EL[i]=getint()-1;
  238. 238 ER[i]=getint()-1;
  239. 239 Ea[i]=getint();
  240. 240 Eb[i]=getint();
  241. 241 }
  242. 242
  243. 243 for(int i=0;i<m;i++) p[i]=i;
  244. 244 stable_sort(p,p+m,cmp);
  245. 245
  246. 246 int curbase=0;
  247. 247
  248. 248 for(int i=0;i<m;i++)
  249. 249 {
  250. 250 int e=p[i]; //the id of current edge.
  251. 251 int cur=n+i; //the id of current edge node.
  252. 252 node*L=T[EL[e]];
  253. 253 node*R=T[ER[e]];
  254. 254 curbase=Ea[e]; //current value count.
  255. 255 T[cur]->v=Eb[e]; //assign value of current edge node.
  256. 256
  257. 257 if(L==R) continue;
  258. 258
  259. 259 if(T.FindRoot(L)==T.FindRoot(R))
  260. 260 {
  261. 261 node*X=T.GetMax(L,R);
  262. 262 int v=X->v;
  263. 263
  264. 264 if(v>Eb[e]) //replace point mxp
  265. 265 {
  266. 266 T.Cut(T[EL[X->code-n]],X);
  267. 267 T.Cut(T[ER[X->code-n]],X);
  268. 268
  269. 269 T.Link(L,T[cur]);
  270. 270 T.Link(R,T[cur]);
  271. 271 }
  272. 272 }
  273. 273 else
  274. 274 {
  275. 275 T.Link(L,T[cur]);
  276. 276 T.Link(R,T[cur]);
  277. 277 }
  278. 278
  279. 279 if(T.FindRoot(T[n-1])==T.FindRoot(T[0]))
  280. 280 {
  281. 281 T.SetRoot(T[n-1]);
  282. 282 T.expend(T[0]);
  283. 283 res=min(res,curbase+T[0]->mxp->v);
  284. 284 }
  285. 285 }
  286. 286
  287. 287 if(res==INF) printf("-1\n");
  288. 288 else printf("%d\n",res);
  289. 289
  290. 290 return 0;
  291. 291 }

View Code

 

 


替罪羊树

AC BZOJ 1588

平衡树/权值线段树裸题.

  1. 1 #include <cstdio>
  2. 2 #include <fstream>
  3. 3 #include <iostream>
  4. 4
  5. 5 #include <cstdlib>
  6. 6 #include <cstring>
  7. 7 #include <algorithm>
  8. 8 #include <cmath>
  9. 9
  10. 10 #include <queue>
  11. 11 #include <vector>
  12. 12 #include <map>
  13. 13 #include <set>
  14. 14 #include <stack>
  15. 15 #include <list>
  16. 16
  17. 17 typedef unsigned int uint;
  18. 18 typedef long long int ll;
  19. 19 typedef unsigned long long int ull;
  20. 20 typedef double db;
  21. 21 typedef long double ldb;
  22. 22
  23. 23 using namespace std;
  24. 24
  25. 25 inline int getint()
  26. 26 {
  27. 27 int res=0;
  28. 28 char c=getchar();
  29. 29 bool mi=false;
  30. 30 while((c<\'0\' || c>\'9\')&&!feof(stdin)) mi=(c==\'-\'),c=getchar();
  31. 31 while((\'0\'<=c && c<=\'9\')&&!feof(stdin)) res=res*10+c-\'0\',c=getchar();
  32. 32 return mi ? -res : res;
  33. 33 }
  34. 34 inline ll getll()
  35. 35 {
  36. 36 ll res=0;
  37. 37 char c=getchar();
  38. 38 bool mi=false;
  39. 39 while(c<\'0\' || c>\'9\') mi=(c==\'-\'),c=getchar();
  40. 40 while(\'0\'<=c && c<=\'9\') res=res*10+c-\'0\',c=getchar();
  41. 41 return mi ? -res : res;
  42. 42 }
  43. 43
  44. 44 //==============================================================================
  45. 45 //==============================================================================
  46. 46 //==============================================================================
  47. 47 //==============================================================================
  48. 48
  49. 49 int f[205000];
  50. 50 int s[205000][2];
  51. 51 int t[205000];
  52. 52 int tot[205000];
  53. 53 int ncnt=0;
  54. 54
  55. 55 int root=0;
  56. 56
  57. 57 int q[205000]; int qt;
  58. 58 void fetch(int x)
  59. 59 { if(!x) return ; fetch(s[x][0]); q[qt++]=x; fetch(s[x][1]); }
  60. 60 int construct(int l=0,int r=qt-1)
  61. 61 {
  62. 62 if(l>r) return 0; //nil
  63. 63 int mid=(l+r)>>1; int x=q[mid]; tot[x]=1;
  64. 64 s[x][0]=construct(l,mid-1); f[s[x][0]]=x; tot[x]+=tot[s[x][0]];
  65. 65 s[x][1]=construct(mid+1,r); f[s[x][1]]=x; tot[x]+=tot[s[x][1]];
  66. 66 return x;
  67. 67 }
  68. 68 int rebuild(int x)
  69. 69 { qt=0; fetch(x); return construct(); }
  70. 70
  71. 71 void balance(int x)
  72. 72 {
  73. 73 int y=0;
  74. 74 while(x)
  75. 75 {
  76. 76 if(tot[x]>=5)
  77. 77 {
  78. 78 db v=db(tot[s[x][0]])/db(tot[x]-1);
  79. 79 if(v<=0.20 || v>=0.80) y=x;
  80. 80 }
  81. 81 x=f[x];
  82. 82 }
  83. 83 if(y)
  84. 84 {
  85. 85 int z=f[y];
  86. 86 if(z)
  87. 87 {
  88. 88 int d=(y==s[z][1]);
  89. 89 s[z][d]=rebuild(y);
  90. 90 f[s[z][d]]=z;
  91. 91 }
  92. 92 else root=rebuild(y),f[root]=0;
  93. 93 }
  94. 94 }
  95. 95
  96. 96 void Insert(int v)
  97. 97 {
  98. 98 int p=++ncnt; t[p]=v; tot[p]=1;
  99. 99 if(!root) { root=p; return ; }
  100. 100 int x=root,y=0;
  101. 101 while(x) tot[x]+=1,y=x,x=s[x][v>=t[x]];
  102. 102 s[y][v>=t[y]]=p; f[p]=y;
  103. 103 balance(p);
  104. 104 }
  105. 105
  106. 106 int Rank(int v)
  107. 107 {
  108. 108 int x=root,res=0;
  109. 109 while(x)
  110. 110 if(v<=t[x]) x=s[x][0];
  111. 111 else res+=tot[s[x][0]]+1,x=s[x][1];
  112. 112 return res;
  113. 113 }
  114. 114
  115. 115 int FindRank(int k)
  116. 116 {
  117. 117 int x=root,y=0;
  118. 118 while(x)
  119. 119 {
  120. 120 y=x;
  121. 121 int c=tot[s[x][0]]+1;
  122. 122 if(k==c) break;
  123. 123 if(k<c) x=s[x][0];
  124. 124 else k-=c,x=s[x][1];
  125. 125 }
  126. 126 return y;
  127. 127 }
  128. 128
  129. 129 int Prefix(int v) { return t[FindRank(Rank(v))]; }
  130. 130 int Suffix(int v) { return t[FindRank(Rank(v)+1)]; }
  131. 131
  132. 132
  133. 133 void op(int x=root)
  134. 134 { if(!x)return; op(s[x][0]); printf("%d[v:%d l:%d r:%d f:%d tot:%d]\n",x,t[x],s[x][0],s[x][1],f[x],tot[x]); op(s[x][1]); }
  135. 135
  136. 136 int n;
  137. 137
  138. 138 inline int abs(int p){ return p&0x80000000 ? -p : p ; }
  139. 139
  140. 140 int main()
  141. 141 {
  142. 142 n=getint();
  143. 143
  144. 144 int res=getint(); Insert(res);
  145. 145 for(int i=1;i<n;i++)
  146. 146 {
  147. 147 int c=getint();
  148. 148 res+=min(abs(c-Prefix(c)),abs(c-Suffix(c)));
  149. 149 Insert(c);
  150. 150 }
  151. 151 printf("%d\n",res);
  152. 152
  153. 153 return 0;
  154. 154 }

View Code

参数调成6:0.8/1,加上读入优化,跑了308ms.

不带删除….rank查询前驱后继……….

常数依然降不下来,晚上写一个线段树版本对比一下效率.

 

 

 …

版权声明:本文为DragoonKiller原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/DragoonKiller/p/4295945.html