1:Trie 字典树

字典树

又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。

它有3个基本性质:根节点不包含字符,除根节点外每一个节点都只包含一个字符。 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。 每个节点的所有子节点包含的字符都不相同。

详细应用见  http://blog.csdn.net/metalseed/article/details/7953262

  1. #include <iostream>
  2. using namespace std;
  3. #define MAX 26 //字符集大小
  4. typedef struct TrieNode {
  5. int nCount;
  6. struct TrieNode *next[MAX];
  7. }TrieNode;
  8. TrieNode Memory[1000000];
  9. int allocp =0;
  10. TrieNode *CreateTrieNode() {
  11. int i;
  12. TrieNode *p;
  13. p = &Memory[allocp++];
  14. p->nCount = 1;
  15. for(i =0 ; i < MAX ; i++) {
  16. p->next[i] = NULL;
  17. }
  18. return p;
  19. }
  20. void InsertTrie(TrieNode * &pRoot , char*s) {
  21. int i, k;
  22. TrieNode *p;
  23. if(!(p = pRoot)) {
  24. p = pRoot = CreateTrieNode();
  25. }
  26. i = 0;
  27. while(s[i]) {
  28. k = s[i++] - 'a';
  29. if(p->next[k])
  30. p->next[k]->nCount++;
  31. else
  32. p->next[k] = CreateTrieNode();
  33. p = p->next[k];
  34. }
  35. }
  36. /*查询该前缀出现次数*/
  37. /*若查询该词出现次数
  38. 则所有的count初始化为0
  39. 并去除所有对count的操作
  40. 只在每次InsertTrie末尾加 p->nCount++;
  41. */
  42. int SearchTrie(TrieNode * &pRoot , char*s) {
  43. TrieNode *p;
  44. int i , k;
  45. if(!(p = pRoot)) {
  46. return 0;
  47. }
  48. i = 0;
  49. while(s[i]) {
  50. k = s[i++] -'a';
  51. if(p->next[k] == NULL) return 0;
  52. p = p->next[k];
  53. }
  54. return p->nCount;
  55. }
  56. int main()
  57. {
  58. TrieNode *ROOT = NULL;
  59. InsertTrie(ROOT,"see");
  60. InsertTrie(ROOT,"seeda");
  61. InsertTrie(ROOT,"seedb");
  62. InsertTrie(ROOT,"seeda");
  63. cout<<SearchTrie(ROOT,"seeda")<<endl;
  64. cout<<SearchTrie(ROOT,"seedb")<<endl;
  65. cout<<SearchTrie(ROOT,"see")<<endl;
  66. return 0;
  67. }

3:BIT 树状数组

1、概述

树状数组(binary indexed tree),是一种设计新颖的数组结构,它能够高效地获取数组中连续n个数的和。概括说,树状数组通常用于解决以下问题:数组{a}中的元素可能不断地被修改,怎样才能快速地获取连续几个数的和?

2、树状数组基本操作

传统数组(共n个元素)的元素修改和连续元素求和的复杂度分别为O(1)和O(n)。树状数组通过将线性结构转换成伪树状结构(线性结构只能逐个扫描元素,而树状结构可以实现跳跃式扫描),使得修改和求和复杂度均为O(lgn),大大提高了整体效率。

详见 : http://blog.csdn.net/metalseed/article/details/7984075   (含2D模板)

  1. #include<iostream>
  2. #include<algorithm>
  3. using namespace std;
  4. /* 1D */
  5. const int maxn = 10000;
  6. int tree[maxn],maxID = 0xff/*数组长度,由题定,建树用update*/;
  7. inline void init()
  8. {
  9. memset(tree,0,sizeof(tree));
  10. }
  11. inline int read(int idx){ /*求前idx项和*/
  12. int sum = 0;
  13. while (idx > 0){
  14. sum += tree[idx];
  15. idx -= (idx & -idx);
  16. }
  17. return sum;
  18. }
  19. inline int readSingle(int idx){ /*求idx单点值*/
  20. int sum = tree[idx];
  21. if (idx > 0){
  22. int z = idx - (idx & -idx);
  23. idx--;
  24. while (idx != z){
  25. sum -= tree[idx];
  26. idx -= (idx & -idx);
  27. }
  28. }
  29. return sum;
  30. }
  31. inline void update(int idx ,int val){  /*给idx位置叠加val,叠加!*/
  32. while (idx <= maxID){
  33. tree[idx] += val;
  34. idx += (idx & -idx);
  35. }
  36. }
  37. int main()
  38. {
  39. cout << read(10) << endl;
  40. for(int i = 0; i< 10; ++i)
  41. {
  42. update(i+1,i+1);
  43. }
  44. update(4,999);
  45. cout << read(1) << endl;
  46. cout << read(3) << endl;
  47. cout << readSingle(4) << endl;
  48. return 0;
  49. }

4:Segment Tree 线段树

成段加C  区间求和

  1. #include <cstdio>
  2. #include <algorithm>
  3. using namespace std;
  4. #define lson l , m , rt << 1
  5. #define rson m + 1 , r , rt << 1 | 1
  6. #define LL long long
  7. const int maxn = 111111;
  8. /* Node Begin */
  9. LL add[maxn<<2];
  10. LL sum[maxn<<2];
  11. /* Node End */
  12. void PushUp(int rt) {
  13. sum[rt] = sum[rt<<1] + sum[rt<<1|1];
  14. }
  15. void PushDown(int rt,int m) {
  16. if (add[rt]) {
  17. add[rt<<1] += add[rt];
  18. add[rt<<1|1] += add[rt];
  19. sum[rt<<1] += add[rt] * (m - (m >> 1));
  20. sum[rt<<1|1] += add[rt] * (m >> 1);
  21. add[rt] = 0;
  22. }
  23. }
  24. void build(int l,int r,int rt) {
  25. add[rt] = 0;
  26. if (l == r) {
  27. scanf("%lld",&sum[rt]);
  28. return ;
  29. }
  30. int m = (l + r) >> 1;
  31. build(lson);
  32. build(rson);
  33. PushUp(rt);
  34. }
  35. void update(int L,int R,int c,int l,int r,int rt) {
  36. if (L <= l && r <= R) {
  37. add[rt] += c;
  38. sum[rt] += (LL)c * (r - l + 1);
  39. return ;
  40. }
  41. PushDown(rt , r - l + 1);
  42. int m = (l + r) >> 1;
  43. if (L <= m) update(L , R , c , lson);
  44. if (m < R) update(L , R , c , rson);
  45. PushUp(rt);
  46. }
  47. LL query(int L,int R,int l,int r,int rt) {
  48. if (L <= l && r <= R) {
  49. return sum[rt];
  50. }
  51. PushDown(rt , r - l + 1);
  52. int m = (l + r) >> 1;
  53. LL ret = 0;
  54. if (L <= m) ret += query(L , R , lson);
  55. if (m < R) ret += query(L , R , rson);
  56. return ret;
  57. }
  58. int main() {
  59. int N , Q;
  60. scanf("%d%d",&N,&Q);
  61. build(1 , N , 1);
  62. while (Q --) {
  63. char op[2];
  64. int a , b , c;
  65. scanf("%s",op);
  66. if (op[0] == 'Q')
  67. {
  68. scanf("%d%d",&a,&b);
  69. printf("%lld\n",query(a , b , 1 , N , 1));
  70. }
  71. else
  72. {
  73. scanf("%d%d%d",&a,&b,&c);
  74. update(a , b , c , 1 , N , 1);
  75. }
  76. }
  77. return 0;
  78. }

5:SBT 二叉平衡检索树

http://acm.hdu.edu.cn/showproblem.php?pid=4006

  1. #include <stdio.h>
  2. #include <string.h>
  3. #define MAX 1000010
  4. int n,m;
  5. struct SBT {
  6. int left,right,size,key;
  7. void Init() {
  8. left = right = 0;
  9. size = 1;
  10. }
  11. }a[MAX];
  12. int tot,root;
  13. void left_rotate(int &t) {
  14. int k = a[t].right;
  15. a[t].right = a[k].left;
  16. a[k].left = t;
  17. a[k].size = a[t].size;
  18. a[t].size = a[a[t].left].size + a[a[t].right].size + 1;
  19. t = k;
  20. }
  21. void right_rotate(int &t) {
  22. int k = a[t].left;
  23. a[t].left = a[k].right;
  24. a[k].right = t;
  25. a[k].size = a[t].size;
  26. a[t].size = a[a[t].left].size + a[a[t].right].size + 1;
  27. t = k;
  28. }
  29. void maintain(int &t,int flag) {
  30. if (flag == 0) {
  31. if (a[a[a[t].left].left].size > a[a[t].right].size)
  32. right_rotate(t);
  33. else if (a[a[a[t].left].right].size > a[a[t].right].size)
  34. left_rotate(a[t].left),right_rotate(t);
  35. else return;
  36. }
  37. else {
  38. if (a[a[a[t].right].right].size > a[a[t].left].size)
  39. left_rotate(t);
  40. else if (a[a[a[t].right].left].size > a[a[t].left].size)
  41. right_rotate(a[t].right),left_rotate(t);
  42. else return;
  43. }
  44. maintain(a[t].left,0);
  45. maintain(a[t].right,1);
  46. maintain(t,0);
  47. maintain(t,1);
  48. }
  49. void insert(int &t,int v) {
  50. if (t == 0)
  51. t = ++tot,a[t].Init(),a[t].key = v;
  52. else {
  53. a[t].size++;
  54. if (v < a[t].key)
  55. insert(a[t].left,v);
  56. else insert(a[t].right,v);
  57. maintain(t,v>=a[t].key);
  58. }
  59. }
  60. int del(int &t,int v) {
  61. if (!t) return 0;
  62. a[t].size--;
  63. if (v == a[t].key || v < a[t].key && !a[t].left
  64. || v > a[t].key && !a[t].right) {
  65. if (a[t].left && a[t].right) {
  66. int p = del(a[t].left,v+1);
  67. a[t].key = a[p].key;
  68. return p;
  69. }
  70. else {
  71. int p = t;
  72. t = a[t].left + a[t].right;
  73. return p;
  74. }
  75. }
  76. else return del(v<a[t].key?a[t].left:a[t].right,v);
  77. }
  78. int find(int t,int k) {
  79. if (k <= a[a[t].left].size)
  80. return find(a[t].left,k);
  81. if (k > a[a[t].left].size + 1)
  82. return find(a[t].right,k-a[a[t].left].size-1);
  83. return a[t].key;
  84. }
  85. int main()
  86. {
  87. int i,j,k;
  88. while (scanf("%d%d",&n,&m) != EOF) {
  89. tot = root = 0;
  90. char ope[10];
  91. while (n--) {
  92. scanf("%s",ope);
  93. if (ope[0] == 'I') {
  94. scanf("%d",&k);
  95. insert(root,k);
  96. }
  97. else printf("%d\n",find(root,a[root].size+1-m));
  98. }
  99. }
  100. }

6:Splay 伸展树

  1. /*
  2. 题意:有N个数字围成一个圈,有M个操作,操作类型有六种:
  3. (1)“add x",从当前指针位置开始的顺时针K2个数加上x。
  4. (2)"reverse",翻转,从当前指针指针位置开始的顺时针的K2个数。
  5. (3)"insert x",在当前指针位置的顺时候方向插入一个数x。
  6. (4)”delete“,删除当前指针所指的数。
  7. (5)"move x”,如果x=1,指针逆时针旋转,如果x=2,顺时针旋转。
  8. (6)“query",查询指针所指向的数的值。
  9. Splay的作法就不说了。
  10. 还可以有三个双端队列加两个标记搞定,方法,是第一个双端队列que1维护前K1个数,
  11. 第二个que2维护第K1+1到第K2个数,第三个que3维护接下的数,标记add,
  12. 表示que1和que2里的数要加上多少,标记head,表示que1是否被翻转过。
  13. Splay(姿势1):
  14. */
  15. #include <iostream>
  16. #include <cstdio>
  17. #include <cstring>
  18. #include <string>
  19. #include <vector>
  20. #include <algorithm>
  21. #include <queue>
  22. #include <set>
  23. #include <map>
  24. using namespace std;
  25. typedef long long LL;
  26. typedef pair<int,int> PII;
  27. #define LL(x)    (ch[x][0])
  28. #define RR(x)    (ch[x][1])
  29. #define Kt       (ch[ ch[Rt][1] ][0])
  30. #define MID(a,b) (a+((b-a)>>1))
  31. const int N=1e6+5;
  32. int n,m,k1,k2;
  33. int a[N/2];
  34. struct SplayTree
  35. {
  36. int Rt,top;
  37. int pre[N],sz[N],ch[N][2];
  38. int key[N],add[N],pos;
  39. bool flip[N];
  40. inline void Link(int x,int y,int f)
  41. {
  42. pre[x]=y; if(y) ch[y][f]=x;
  43. }
  44. inline void Rotate(int x,int f)
  45. {
  46. int y=pre[x],z=pre[y];
  47. PushDown(y); PushDown(x);
  48. Link(x,z,RR(z)==y);
  49. Link(ch[x][f],y,!f);
  50. Link(y,x,f);
  51. PushUp(y);
  52. }
  53. inline void Splay(int x,int goal)
  54. {
  55. while(pre[x]!=goal)
  56. {
  57. int y=pre[x],z=pre[y];
  58. int cx=(LL(y)==x),cy=(LL(z)==y);
  59. if(z==goal) Rotate(x,cx);
  60. else
  61. {
  62. if(cx==cy) Rotate(y,cy);
  63. else Rotate(x,cx);
  64. Rotate(x,cy);
  65. }
  66. }
  67. PushUp(x);
  68. if(goal==0) Rt=x;
  69. }
  70. inline void Select(int K,int goal)
  71. {
  72. int x=Rt;
  73. PushDown(x);
  74. while(1)
  75. {
  76. if(sz[LL(x)]>=K) x=LL(x);
  77. else if(sz[LL(x)]+1==K) break;
  78. else K-=sz[LL(x)]+1,x=RR(x);
  79. PushDown(x);
  80. }
  81. Splay(x,goal);
  82. }
  83. inline void fun_add(int x,int valu)
  84. {
  85. add[x]+=valu;
  86. key[x]+=valu;
  87. }
  88. inline void fun_flip(int x)
  89. {
  90. flip[x]^=1;
  91. swap(LL(x),RR(x));
  92. }
  93. inline void PushDown(int x)
  94. {
  95. if(add[x])
  96. {
  97. fun_add(LL(x),add[x]);
  98. fun_add(RR(x),add[x]);
  99. add[x]=0;
  100. }
  101. if(flip[x])
  102. {
  103. fun_flip(LL(x));
  104. fun_flip(RR(x));
  105. flip[x]=0;
  106. }
  107. }
  108. inline void PushUp(int x)
  109. {
  110. sz[x]=1+sz[LL(x)]+sz[RR(x)];
  111. }
  112. inline void Add(int x)
  113. {
  114. Select(1,0); Select(k2+2,Rt);
  115. fun_add(Kt,x);
  116. }
  117. inline void Reverse()
  118. {
  119. Select(1,0); Select(k1+2,Rt);
  120. fun_flip(Kt);
  121. }
  122. inline void Insert(int x,int pos)
  123. {
  124. Select(pos,0); Select(pos+1,Rt);
  125. addNode(x,Kt,RR(Rt));
  126. PushUp(RR(Rt)); PushUp(Rt);
  127. }
  128. inline int Delete(bool top)
  129. {
  130. int valu;
  131. if(top)
  132. {
  133. Select(1,0);    Select(3,Rt);
  134. valu=key[Kt];
  135. Kt=0;
  136. PushUp(RR(Rt)); PushUp(Rt);
  137. }
  138. else
  139. {
  140. int len=sz[Rt];
  141. Select(len-2,0);Select(len,Rt);
  142. valu=key[Kt];
  143. Kt=0;
  144. PushUp(RR(Rt)); PushUp(Rt);
  145. }
  146. return valu;
  147. }
  148. inline void Move(int x)
  149. {
  150. if(x==1)
  151. {
  152. int valu=Delete(0);
  153. Insert(valu,1);
  154. }
  155. else
  156. {
  157. int valu=Delete(1);
  158. Insert(valu,sz[Rt]-1);
  159. }
  160. }
  161. inline void Query()
  162. {
  163. Select(2,0);
  164. printf("%d\n",key[Rt]);
  165. }
  166. //    void Debug(){ printf("Rt:%d\n",Rt); Travel(Rt); }
  167. //    void Travel(int x)
  168. //    {
  169. //        if(x==0) return;
  170. //
  171. //        PushDown(x);
  172. //        Travel(LL(x));
  173. //        printf("node:%d,pre:%d,sz:%d,LL:%d,RR:%d,key:%d\n",
  174. //               x,pre[x],sz[x],LL(x),RR(x),key[x]);
  175. //        Travel(RR(x));
  176. //    }
  177. void addNode(int valu,int &x,int f)
  178. {
  179. x=++top;
  180. pre[x]=f; sz[x]=1; LL(x)=RR(x)=0;
  181. key[x]=valu; add[x]=flip[x]=0;
  182. }
  183. void build(int lft,int rht,int &x,int f)
  184. {
  185. if(lft>rht) return;
  186. int mid=MID(lft,rht);
  187. addNode(a[mid],x,f);
  188. build(lft,mid-1,LL(x),x);
  189. build(mid+1,rht,RR(x),x);
  190. PushUp(x);
  191. }
  192. void init()
  193. {
  194. Rt=top=0;
  195. pre[0]=sz[0]=LL(0)=RR(0)=0;
  196. addNode(0,Rt,0);    addNode(0,RR(Rt),Rt);
  197. build(0,n-1,Kt,RR(Rt));
  198. PushUp(RR(Rt));     PushUp(Rt);
  199. }
  200. }spt;
  201. int main()
  202. {
  203. int t_cnt=0;
  204. while(scanf("%d%d%d%d",&n,&m,&k1,&k2)!=EOF)
  205. {
  206. if(n==0&&m==0&&k1==0&&k2==0) break;
  207. for(int i=0;i<n;i++) scanf("%d",&a[i]);
  208. spt.init();
  209. printf("Case #%d:\n",++t_cnt);
  210. char op[100]; int x;
  211. while(m--)
  212. {
  213. scanf("%s",op);
  214. if(op[0]=='a')
  215. {
  216. scanf("%d",&x); spt.Add(x);
  217. }
  218. else if(op[0]=='r') spt.Reverse();
  219. else if(op[0]=='i')
  220. {
  221. scanf("%d",&x); spt.Insert(x,2);
  222. }
  223. else if(op[0]=='d') spt.Delete(1);
  224. else if(op[0]=='m')
  225. {
  226. scanf("%d",&x); spt.Move(x);
  227. }
  228. else spt.Query();
  229. }
  230. }
  231. return 0;
  232. }
  233. Spaly(姿势2):
  234. #include <iostream>
  235. #include <cstdio>
  236. #include <cstring>
  237. using namespace std;
  238. #define LL(x) (ch[x][0])
  239. #define RR(x) (ch[x][1])
  240. #define Kt    (ch[ ch[Rt][1] ][0])
  241. #define MID(a,b)   (a+((b-a)>>1))
  242. const int N=1e6+5;
  243. int a[N/2];
  244. int n,m,K1,K2,pos;
  245. struct SplayTree
  246. {
  247. int Rt,top;
  248. int sz[N],pre[N],ch[N][2];
  249. bool flip[N];
  250. int key[N],add[N];
  251. inline void Link(int x,int y,int f)
  252. {
  253. pre[x]=y; if(y) ch[y][f]=x;
  254. }
  255. inline void Rotate(int x,int f)
  256. {
  257. int y=pre[x],z=pre[y];
  258. PushDown(y); PushDown(x);
  259. Link(x,z,RR(z)==y);
  260. Link(ch[x][f],y,!f);
  261. Link(y,x,f);
  262. PushUp(y);
  263. }
  264. inline void Splay(int x,int goal)
  265. {
  266. while(pre[x]!=goal)
  267. {
  268. int y=pre[x],z=pre[y];
  269. int cx=(LL(y)==x),cy=(LL(z)==y);
  270. if(z==goal) Rotate(x,cx);
  271. else
  272. {
  273. if(cx==cy) Rotate(y,cy);
  274. else Rotate(x,cx);
  275. Rotate(x,cy);
  276. }
  277. }
  278. PushUp(x);
  279. if(goal==0) Rt=x;
  280. }
  281. inline void Select(int K,int goal)
  282. {
  283. int x=Rt;
  284. PushDown(x);
  285. while(1)
  286. {
  287. if(sz[LL(x)]>=K) x=LL(x);
  288. else if(1+sz[LL(x)]==K) break;
  289. else K-=sz[LL(x)]+1,x=RR(x);
  290. PushDown(x);
  291. }
  292. Splay(x,goal);
  293. }
  294. inline void fun_add(int x,int valu)
  295. {
  296. key[x]+=valu;
  297. add[x]+=valu;
  298. }
  299. inline void fun_flip(int x)
  300. {
  301. flip[x]^=1;
  302. swap(LL(x),RR(x));
  303. }
  304. inline void PushUp(int x)
  305. {
  306. sz[x]=1+sz[LL(x)]+sz[RR(x)];
  307. }
  308. inline void PushDown(int x)
  309. {
  310. if(add[x])
  311. {
  312. fun_add(LL(x),add[x]);
  313. fun_add(RR(x),add[x]);
  314. add[x]=0;
  315. }
  316. if(flip[x])
  317. {
  318. fun_flip(LL(x)); fun_flip(RR(x));
  319. flip[x]=0;
  320. }
  321. }
  322. inline void Add(int st,int ed,int valu)
  323. {
  324. Select(st-1,0); Select(ed+1,Rt);
  325. fun_add(Kt,valu);
  326. }
  327. inline void Reverse(int st,int ed)
  328. {
  329. Select(st-1,0); Select(ed+1,Rt);
  330. fun_flip(Kt);
  331. }
  332. inline void Insert(int pos,int valu)
  333. {
  334. Select(pos,0);  Select(pos+1,Rt);
  335. addNode(valu,Kt,RR(Rt));
  336. PushUp(RR(Rt)); PushUp(Rt);
  337. }
  338. inline void Delete(int pos)
  339. {
  340. Select(pos-1,0); Select(pos+1,Rt);
  341. Kt=0;  PushUp(RR(Rt)); PushUp(Rt);
  342. }
  343. inline void Query(int pos)
  344. {
  345. Select(pos,0);
  346. printf("%d\n",key[Rt]);
  347. }
  348. inline void Move(int len)
  349. {
  350. pos-=len;
  351. Select(1,0);    Select(2+len,Rt);
  352. int r1=Kt;      Kt=0;
  353. PushUp(RR(Rt)); PushUp(Rt);
  354. Select(sz[Rt]-1,0); Select(sz[Rt],Rt);
  355. Link(r1,RR(Rt),0);
  356. PushUp(RR(Rt)); PushUp(Rt);
  357. }
  358. inline void addNode(int valu,int &x,int f)
  359. {
  360. x=++top;
  361. sz[x]=1; pre[x]=f; LL(x)=RR(x)=0;
  362. key[x]=valu; add[x]=flip[x]=0;
  363. }
  364. void build(int lft,int rht,int &x,int f)
  365. {
  366. if(lft>rht) return;
  367. int mid=MID(lft,rht);
  368. addNode(a[mid],x,f);
  369. build(lft,mid-1,LL(x),x);
  370. build(mid+1,rht,RR(x),x);
  371. PushUp(x);
  372. }
  373. void init()
  374. {
  375. Rt=top=0;
  376. addNode(0,Rt,0); addNode(0,RR(Rt),Rt);
  377. build(0,n-1,Kt,RR(Rt));
  378. PushUp(RR(Rt));  PushUp(Rt);
  379. }
  380. //    void Debug(){ printf("Rt:%d\n",Rt); Travel(Rt); }
  381. //    void Travel(int x)
  382. //    {
  383. //        if(x==0) return;
  384. //        PushDown(x);
  385. //        Travel(LL(x));
  386. //        printf("node:%d,sz:%d,pre:%d,LL:%d,RR:%d,key:%d\n",
  387. //               x,sz[x],pre[x],LL(x),RR(x),key[x]);
  388. //        Travel(RR(x));
  389. //    }
  390. }spt;
  391. void deal(int &pos,int len)
  392. {
  393. if(pos<=1) pos=len-1;
  394. if(pos>=len) pos=2;
  395. }
  396. int main()
  397. {
  398. freopen("in.txt","r",stdin);
  399. int t_cnt=0;
  400. while(scanf("%d%d%d%d",&n,&m,&K1,&K2)!=EOF)
  401. {
  402. if(n==0&&m==0&&K1==0&&K2==0) break;
  403. for(int i=0;i<n;i++) scanf("%d",&a[i]);
  404. spt.init(); pos=2;
  405. printf("Case #%d:\n",++t_cnt);
  406. char op[100]; int x;
  407. while(m--)
  408. {
  409. int len=spt.sz[spt.Rt];
  410. scanf("%s",op);
  411. if(op[0]=='a')
  412. {
  413. scanf("%d",&x);
  414. if(pos+K2>len) spt.Move(pos+K2-len);
  415. spt.Add(pos,pos+K2-1,x);
  416. }
  417. else if(op[0]=='r')
  418. {
  419. if(pos+K1>=len) spt.Move(pos+K1-len);
  420. spt.Reverse(pos,pos+K1-1);
  421. }
  422. else if(op[0]=='i')
  423. {
  424. scanf("%d",&x); spt.Insert(pos,x);
  425. }
  426. else if(op[0]=='d')
  427. {
  428. spt.Delete(pos);
  429. deal(pos,spt.sz[spt.Rt]);
  430. }
  431. else if(op[0]=='m')
  432. {
  433. scanf("%d",&x);
  434. if(x==1) pos--;
  435. else pos++;
  436. deal(pos,len);
  437. }
  438. else if(op[0]=='q') spt.Query(pos);
  439. //            spt.Debug();
  440. }
  441. }
  442. return 0;
  443. }
  444. /*
  445. Description
  446. You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
  447. Input
  448. The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
  449. The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
  450. Each of the next Q lines represents an operation.
  451. "C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
  452. "Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
  453. Output
  454. You need to answer all Q commands in order. One answer in a line.
  455. Sample Input
  456. 10 5
  457. 1 2 3 4 5 6 7 8 9 10
  458. Q 4 4
  459. Q 1 10
  460. Q 2 4
  461. C 3 6 3
  462. Q 2 4
  463. Sample Output
  464. 4
  465. 55
  466. 9
  467. 15
  468. http://acm.pku.edu.cn/JudgeOnline/problem?id=3468
  469. 区间跟新,区间求和
  470. */
  471. #include <cstdio>
  472. #define keyTree (ch[ ch[root][1] ][0])
  473. const int maxn = 222222;
  474. struct SplayTree{
  475. int sz[maxn];
  476. int ch[maxn][2];
  477. int pre[maxn];
  478. int root , top1 , top2;
  479. int ss[maxn] , que[maxn];
  480. inline void Rotate(int x,int f) {
  481. int y = pre[x];
  482. push_down(y);
  483. push_down(x);
  484. ch[y][!f] = ch[x][f];
  485. pre[ ch[x][f] ] = y;
  486. pre[x] = pre[y];
  487. if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] = x;
  488. ch[x][f] = y;
  489. pre[y] = x;
  490. push_up(y);
  491. }
  492. inline void Splay(int x,int goal) {
  493. push_down(x);
  494. while(pre[x] != goal) {
  495. if(pre[pre[x]] == goal) {
  496. Rotate(x , ch[pre[x]][0] == x);
  497. } else {
  498. int y = pre[x] , z = pre[y];
  499. int f = (ch[z][0] == y);
  500. if(ch[y][f] == x) {
  501. Rotate(x , !f) , Rotate(x , f);
  502. } else {
  503. Rotate(y , f) , Rotate(x , f);
  504. }
  505. }
  506. }
  507. push_up(x);
  508. if(goal == 0) root = x;
  509. }
  510. inline void RotateTo(int k,int goal) {//把第k位的数转到goal下边
  511. int x = root;
  512. push_down(x);
  513. while(sz[ ch[x][0] ] != k) {
  514. if(k < sz[ ch[x][0] ]) {
  515. x = ch[x][0];
  516. } else {
  517. k -= (sz[ ch[x][0] ] + 1);
  518. x = ch[x][1];
  519. }
  520. push_down(x);
  521. }
  522. Splay(x,goal);
  523. }
  524. inline void erase(int x) {//把以x为祖先结点删掉放进内存池,回收内存
  525. int father = pre[x];
  526. int head = 0 , tail = 0;
  527. for (que[tail++] = x ; head < tail ; head ++) {
  528. ss[top2 ++] = que[head];
  529. if(ch[ que[head] ][0]) que[tail++] = ch[ que[head] ][0];
  530. if(ch[ que[head] ][1]) que[tail++] = ch[ que[head] ][1];
  531. }
  532. ch[ father ][ ch[father][1] == x ] = 0;
  533. pushup(father);
  534. }
  535. //以上一般不修改//
  536. void debug() {printf("%d\n",root);Treaval(root);}
  537. void Treaval(int x) {
  538. if(x) {
  539. Treaval(ch[x][0]);
  540. printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);
  541. Treaval(ch[x][1]);
  542. }
  543. }
  544. //以上Debug
  545. //以下是题目的特定函数:
  546. inline void NewNode(int &x,int c) {
  547. if (top2) x = ss[--top2];//用栈手动压的内存池
  548. else x = ++top1;
  549. ch[x][0] = ch[x][1] = pre[x] = 0;
  550. sz[x] = 1;
  551. val[x] = sum[x] = c;/*这是题目特定函数*/
  552. add[x] = 0;
  553. }
  554. //把延迟标记推到孩子
  555. inline void push_down(int x) {/*这是题目特定函数*/
  556. if(add[x]) {
  557. val[x] += add[x];
  558. add[ ch[x][0] ] += add[x];
  559. add[ ch[x][1] ] += add[x];
  560. sum[ ch[x][0] ] += (long long)sz[ ch[x][0] ] * add[x];
  561. sum[ ch[x][1] ] += (long long)sz[ ch[x][1] ] * add[x];
  562. add[x] = 0;
  563. }
  564. }
  565. //把孩子状态更新上来
  566. inline void push_up(int x) {
  567. sz[x] = 1 + sz[ ch[x][0] ] + sz[ ch[x][1] ];
  568. /*这是题目特定函数*/
  569. sum[x] = add[x] + val[x] + sum[ ch[x][0] ] + sum[ ch[x][1] ];
  570. }
  571. /*初始化*/
  572. inline void makeTree(int &x,int l,int r,int f) {
  573. if(l > r) return ;
  574. int m = (l + r)>>1;
  575. NewNode(x , num[m]);        /*num[m]权值改成题目所需的*/
  576. makeTree(ch[x][0] , l , m - 1 , x);
  577. makeTree(ch[x][1] , m + 1 , r , x);
  578. pre[x] = f;
  579. push_up(x);
  580. }
  581. inline void init(int n) {/*这是题目特定函数*/
  582. ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0;
  583. add[0] = sum[0] = 0;
  584. root = top1 = 0;
  585. //为了方便处理边界,加两个边界顶点
  586. NewNode(root , -1);
  587. NewNode(ch[root][1] , -1);
  588. pre[top1] = root;
  589. sz[root] = 2;
  590. for (int i = 0 ; i < n ; i ++) scanf("%d",&num[i]);
  591. makeTree(keyTree , 0 , n-1 , ch[root][1]);
  592. push_up(ch[root][1]);
  593. push_up(root);
  594. }
  595. /*更新*/
  596. inline void update( ) {/*这是题目特定函数*/
  597. int l , r , c;
  598. scanf("%d%d%d",&l,&r,&c);
  599. RotateTo(l-1,0);
  600. RotateTo(r+1,root);
  601. add[ keyTree ] += c;
  602. sum[ keyTree ] += (long long)c * sz[ keyTree ];
  603. }
  604. /*询问*/
  605. inline void query() {/*这是题目特定函数*/
  606. int l , r;
  607. scanf("%d%d",&l,&r);
  608. RotateTo(l-1 , 0);
  609. RotateTo(r+1 , root);
  610. printf("%lld\n",sum[keyTree]);
  611. }
  612. /*这是题目特定变量*/
  613. int num[maxn];
  614. int val[maxn];
  615. int add[maxn];
  616. long long sum[maxn];
  617. }spt;
  618. int main() {
  619. int n , m;
  620. scanf("%d%d",&n,&m);
  621. spt.init(n);
  622. while(m --) {
  623. char op[2];
  624. scanf("%s",op);
  625. if(op[0] == 'Q') {
  626. spt.query();
  627. } else {
  628. spt.update();
  629. }
  630. }
  631. return 0;
  632. }

7:动态树

8:斯坦纳树

9:主席树

10:QTree

数据结构---各种树模板相关推荐

  1. 前端笔试常考设计模式,操作系统,数据结构,ACM模板,经典算法,正则表达式,常用方法

    考试时允许使用草稿纸,请提前准备纸笔.考试过程中允许上厕所等短暂离开,但请控制离开时间 笔试得分60%一般通过,面试答对80%才能通过 合集:2023年最全前端面试题考点HTML5+CSS3+JS+V ...

  2. 数据结构0类模板的使用

    类模板的使用 #include <iostream> #include <conio.h> #include <string> #define N 3 using ...

  3. 常用数据结构算法 c++模板实现

    由于大三下学期了,快要找工作了,所以最近在复习一些学过的内容,以下是这几天写的数据结构里面的一些常用的算法,仅供参考.不过在平时做项目的时候,建议采用STL和Boost里面现成的东西,而不要自己去实现 ...

  4. 数据结构——划分树模板

    http://www.notonlysuccess.com/index.php/divide-tree/ http://blog.sina.com.cn/s/blog_5f5353cc0100ki2e ...

  5. ACM常用模板-数据结构

    数据结构方面常用模板总结,大多数代码摘自网络,个人整理总结 string: 任意进制转换:itoa(int n,char* s,int r) //将10进制n转换为r进制并赋给s流:#include& ...

  6. php 掌握jquery,完全掌握jquery tmpl模板

    之前用模板渲染都是用angular,无意间发现了jquery tmpl这种轻量级,其文档在这里,本文主要为大家带来一篇jquery tmpl模板(实例讲解).小编觉得挺不错的,现在就分享给大家,也给大 ...

  7. 算法模版:模拟数据结构之绪论【沈七】

    算法模版:模拟数据结构之绪论 前言 什么是数据结构? 先看数据 再看结构 一些术语 逻辑结构 储存结构 完结散花 参考文献 前言 唤我沈七就好. 算下来应该是有两周没更新了. 是因为最近一直在研究数据 ...

  8. 【Sofice小司笔记】2 算法与数据结构,各类基础及常用高级数据结构、各种搜索方法、动态规划、字符串、数论、编码学、排序等,大部分都基于java实现

    维基百科算法与数据结构 ACM模式模板: import java.io.*; import java.util.*; public class Main{public static void main ...

  9. 《C++ Primer Plus》读书笔记 第16章 string类和标准模板库

    第16章 string类和标准模板库 1.string类 表16.1列出了string类的几个构造函数.其中NBTS(null-terminated string)表示以空字符结束的传统C-风格字符串 ...

最新文章

  1. 备忘录:CISCO router ENABLE crack
  2. aws 服务器之间文件转发,aws bucket之间相互拷贝数据
  3. 服务器跑python程序后还能安装网站吗_如何在服务器上跑python程序
  4. OpenCASCADE:环境变量
  5. ADO.NET 2.0 中的新增 DataSet 功能
  6. macbook pro python开发_Mac打造python2 python3开发环境
  7. 深入理解InnoDB(8)—单表访问
  8. unsigned int mysql_mysql 中int类型字段unsigned和signed的探索
  9. python 数据流中的移动平均值_剑指Offer-41-数据流中的中位数
  10. 美团被曝杀熟外卖会员,回应:定位偏差导致
  11. 51nod-1422:沙拉酱前缀
  12. .NET Core中间件的注册和管道的构建(2)---- 用UseMiddleware扩展方法注册中间件类...
  13. Paraview源码解析8: vtkPVGlyphFilter类
  14. imagej得到灰度图数据_【原创】imagej使用达人指南,分享给大家!
  15. 梅森质数(2^n - 1是质数,则n是质数)的证明
  16. CSDN如何开启版权声明
  17. 一文搞懂CSS 3D动画效果
  18. 系统封装到底有个什么用
  19. 内网渗透-PTHPTTPTK
  20. 数学单位M和单位B是什么意思

热门文章

  1. 【Java 虚拟机原理】垃圾回收算法( Java VisualVM 工具 | 安装 Visual GC 插件 | 使用 Java VisualVM 分析 GC 内存 )
  2. Hadoop前期准备--centos7
  3. 导入jar包和创建jar文件
  4. springmvc整合redis架构搭建实例
  5. [原创] Legato 8.1 oracle full backup skip 奇怪的问题处理过程 -- 非调度日期手工运行调度也不成功(skip)...
  6. JavaScript判断图片是否加载完成的三种方式
  7. 关于UIWebView与js交互的问题
  8. OSI与TCP/IP协议区别
  9. zip unzip 命令
  10. 漫谈WinCE输入法的编写(四)