用树状数组和线段树会比较简单,这里用这道题来学习Splay。

第一次写,代码比较丑

  1. /*
  2. 初始化添加一个key值足够大的结点
  3. 保证每个需要的结点都有后继
  4. */
  5. #include <iostream>
  6. #include <cstdio>
  7. #define ll long long
  8. using namespace std;
  9.  
  10. const int MAXN = , INF = 0x7fffffff;
  11.  
  12. struct node {
  13. //需要的记录信息
  14. ll key, val, sum, lazy, Size, Cnt;
  15. //指向儿子和父亲的指针
  16. node *ch[], *pre;
  17. node() {pre = ch[] = ch [] = ; Size = ; key = ;}
  18. node (ll key) : key (key) {pre = ch[] = ch[] = ; Size = , Cnt = , lazy = ;}
  19. void Csize() {
  20. Size = Cnt;
  21. if (ch[] != NULL) Size += ch[]->Size;
  22. if (ch[] != NULL) Size += ch[]->Size;
  23. }
  24. void Csum() {
  25. sum = val;
  26. if (ch[] != NULL) sum += ch[]->sum + ch[]->Size * ch[]->lazy;
  27. if (ch[] != NULL) sum += ch[]->sum + ch[]->Size * ch[]->lazy;
  28. }
  29. } nil (), *NIL = &nil;
  30.  
  31. struct Splay {
  32. node *root, nod[MAXN];
  33. int ncnt;//计算key值不同的结点数,已去重
  34. Splay() {
  35. ncnt = ;
  36. root = & (nod[ncnt++] = node (INF) );
  37. root->pre = NIL;
  38. root->val = root->sum = ;
  39. }
  40. void Push_Down (node *x) {
  41. if (x->lazy != ) {
  42. if (x->ch[] != NULL) x->ch[]->lazy += x->lazy;
  43. if (x->ch[] != NULL) x->ch[]->lazy += x->lazy;
  44. x->val+=x->lazy;
  45. }
  46. x->lazy = ;
  47. }
  48.  
  49. void Update (node *x) {
  50. x->Csize();
  51. x->Csum();
  52. }
  53.  
  54. void Rotate (node *x, int sta) { //单旋转操作,0左旋,1右旋
  55. node *p = x->pre, *g = p->pre;
  56. Push_Down (p), Push_Down (x);
  57. p->ch[!sta] = x->ch[sta];
  58. if (x->ch[sta] != NULL) x->ch[sta]->pre = p;
  59. x->pre = g;
  60. if (g != NIL)
  61. if (g->ch[] == p) g->ch[] = x;
  62. else g->ch[] = x;
  63. x->ch[sta] = p, p->pre = x, Update (p);
  64. if (p == root ) root = x;
  65. }
  66.  
  67. void splay (node *x, node *y) { //Splay 操作,表示把结点x,转到根
  68. for (Push_Down (x) ; x->pre != y;) { //将x的标记往下传
  69. if (x->pre->pre == y) { //目标结点为父结点
  70. if (x->pre->ch[] == x) Rotate (x, );
  71. else Rotate (x, );
  72. }
  73. else {
  74. node *p = x->pre, *g = p->pre;
  75. if (g->ch[] == p)
  76. if (p->ch[] == x)
  77. Rotate (p, ), Rotate (x, );// / 一字型双旋转
  78. else
  79. Rotate (x, ), Rotate (x, );// < 之字形双旋转
  80.  
  81. else if (p ->ch[] == x)
  82. Rotate (p, ), Rotate (x, );// \ 一字型旋转
  83. else
  84. Rotate (x, ), Rotate (x, ); // >之字形旋转
  85. }
  86. }
  87. Update (x); //维护x结点
  88. }
  89. //找到中序便利的第K个结点,并旋转至结点y的下面。
  90. void Select (int k, node *y) {
  91. int tem ;
  92. node *t ;
  93. for ( t = root; ; ) {
  94. Push_Down (t) ; //标记下传
  95. tem = t->ch[]->Size ;
  96. if (k == tem + ) break ; //找到了第k个结点 t
  97. if (k <= tem)
  98. t = t->ch[] ; //第k个结点在左子树
  99. else
  100. k -= tem + , t = t->ch[] ;//在右子树
  101. }
  102. splay (t, y);
  103. }
  104. bool Search (ll key, node *y) {
  105. node *t = root;
  106. for (; t != NULL;) {
  107. Push_Down (t);
  108. if (t->key > key && t->ch[] != NULL) t = t->ch[];
  109. else if (t->key < key && t->ch[] != NULL) t = t->ch[];
  110. else
  111. break;
  112. }
  113. splay (t, y);
  114. return t->key == key;
  115. }
  116. void Insert (int key, int val) {
  117. if (Search (key, NIL) ) root->Cnt++, root->Size++;
  118. else {
  119. int d = key > root->key;
  120. node *t = & (nod[++ncnt] = node (key) );
  121. Push_Down (root);
  122. t->val = t->sum = val;
  123. t->ch[d] = root->ch[d];
  124. if (root->ch[d] != NULL) root->ch[d]->pre = t;
  125. t->ch[!d] = root;
  126. t->pre = root->pre;
  127. root->pre = t;
  128. root->ch[d] = NULL;
  129. Update (root);
  130. root = t;
  131. }
  132. Update (root);
  133. }
  134. } sp;
  135.  
  136. ll n, m, x;
  137. int main() {
  138. scanf ("%lld %lld", &n, &m);
  139. sp.Insert (, );
  140. sp.Insert (n + , );
  141. for (int i = ; i <= n; i++) {
  142. scanf ("%lld", &x);
  143. sp.Insert (i, x);
  144. }
  145. char cmd;
  146. int l, r;
  147. for (int i = ; i <= m; i++) {
  148. scanf ("\n%c %d %d", &cmd, &l, &r);
  149. sp.Search (l - , NIL);
  150. sp.Search (r + , sp.root);
  151. if (cmd == 'Q') {
  152. node *t = sp.root->ch[]->ch[];
  153. ll ans = t->sum + t->Size * t->lazy;
  154. printf ("%lld\n", ans);
  155. }
  156. if (cmd == 'C') {
  157. ll c;
  158. scanf ("%lld", &c);
  159. sp.root->ch[]->ch[]->lazy += c;
  160. }
  161. }
  162. return ;
  163. }

POJ 3468.A Simple Problem with Integers 解题报告的更多相关文章

  1. POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询)

    POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询) 题意分析 注意一下懒惰标记,数据部分和更新时的数字都要是long long ,别的没什么大 ...

  2. poj 3468 A Simple Problem with Integers 【线段树-成段更新】

    题目:id=3468" target="_blank">poj 3468 A Simple Problem with Integers 题意:给出n个数.两种操作 ...

  3. 线段树(成段更新) POJ 3468 A Simple Problem with Integers

    题目传送门 /* 线段树-成段更新:裸题,成段增减,区间求和 注意:开long long:) */ #include <cstdio> #include <iostream> ...

  4. poj 3468 A Simple Problem with Integers(线段树+区间更新+区间求和)

    题目链接:id=3468http://">http://poj.org/problem? id=3468 A Simple Problem with Integers Time Lim ...

  5. POJ 3468 A Simple Problem with Integers(分块入门)

    题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit ...

  6. POJ 3468 A Simple Problem with Integers(线段树功能:区间加减区间求和)

    题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit ...

  7. [ACM] poj 3468 A Simple Problem with Integers(段树,为段更新,懒惰的标志)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 55273   ...

  8. poj 3468 A Simple Problem with Integers 线段树区间加,区间查询和

    A Simple Problem with Integers Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://poj.org/problem?i ...

  9. poj 3468 A Simple Problem with Integers 线段树区间加,区间查询和(模板)

    A Simple Problem with Integers Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://poj.org/problem?i ...

随机推荐

  1. HDU -- 4496

    D-City Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Subm ...

  2. loadrunner打不开ie&ie默认浏览器设置方法

    loadrunner使用过程中频繁的出现问题,出现次数最多的就是lr打不开ie,或者ie一闪就关闭了,问题出在我默认浏览器的设置上,因为我原先并没有成功设置ie为默认浏览器.这是一个无意识的错误,我以 ...

  3. VS2010 快速写入注释小技巧

    /************************************************************************//*  *//******************* ...

  4. cocos2d的ARC开启

    ARC,官方解释是Automatic Reference Counting,是Apple公司从iOS5开始为开发者新添加的一个功能. 相信很多写移动开发,可能不只是移动开发的人都深有体会,创建一个对象 ...

  5. [git] git 的基本认知

    版本管理 ( Version Control ) 版本管理系统是一个记录文件变更的系统,让你在一段时间后可以恢复指定版本的文件.版本管理系统大致可分为三类:独立的本地版本管理系统.中心化版本管理系统. ...

  6. STL之set、multiset、functor&pair使用方法

    set是一个集合容器,其中包含的元素是唯一的,集合中的元素是按照一定的顺序排列的.元素插入过程是按照排序规则插入,所以不能使用指定位置插入. set采用红黑树变体的数据结构实现,红黑树属于平衡二叉树. ...

  7. openStack 性能开测-2

  8. python处理xml的常用包(lib.xml、ElementTree、lxml)

    python处理xml的三种常见机制 dom(随机访问机制) sax(Simple APIs for XML,事件驱动机制) etree python处理xml的三种包 标准库中的xml Fredri ...

  9. iOS开发总结-类似京东分类,UICollectionView

    // // TypeViewController.m // BJ // // Created by shirenfeng on 16/11/6. // Copyright © 2016年 com.ws ...

  10. C:\WINDOWS\system32\drivers\etc\hosts host文件夹里面的内容是什么?

    这个文件是根据TCP/IP for Windows 的标准来工作的,它的作用是包含IP地址和Host name(主机名)的映射关系,是一个映射IP地址和Host name(主机名)的规定,规定要求每段 ...