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

题目大意:对于一个给定序列,序列内所有数的初始值为0,有4种操作。1:区间(x, y)内的所有数字全部加上C;2:区间(x, y)内所有数字全部乘C; 3:区间(x, y)内的所有数字全部重置为C;

4:输出区间(x, y)内所有数字的P次方的和。由于题目为多实例(至少10组样例),故很耿直的更新到叶子节点明显会TLE;因此需优化。可发现题目所有操作都是对区间进行,因此只需要更新

到区间内数字相同即可。再者注意可进行状态压缩,不需要的累加和累乘只标记即可,需要此部分时再往下更新;更新时先更新3,因为3会覆盖掉1和2;之后再进行累乘,因为累乘影响累加,累

加不影响累乘。注意细节即可。

  1. ///至少10组样例,则八秒实际上不多,需优化。
  2. ///由于所有操作都是对区间进行,故数字保存情况为
  3. ///分区间相同,因此只需要操作到区间数字相同时即可,不必处理到最下面的叶子节点
  4. #include <stdio.h>
  5. #include <algorithm>
  6. using namespace std;
  7. #define N 110000
  8. #define mod 10007
  9. #define lson rt<<1
  10. #define rson rt<<1|1
  11. struct tree
  12. {
  13. int l, r, add, mul, op, num;
  14. ///add记录累加的数,mul记录累乘的数,op记录操作的状态
  15. ///op为1表示区间内数字相同,op为0表示区间内数字不同,需向下
  16. ///继续进行操作,op为2表示区间被重新赋值,需向下更新(操作3)。
  17. int len()
  18. {
  19. return r-l+1;
  20. }
  21. }a[N<<2];
  22. void build(int l, int r, int rt)///初始化
  23. {
  24. a[rt].l = l;
  25. a[rt].r = r;
  26. a[rt].mul = a[rt].op = 1;
  27. a[rt].add = a[rt].num = 0;
  28. if(l==r)return ;
  29. int mid = (l+r)/2;
  30. build(l, mid, lson);
  31. build(mid+1, r, rson);
  32. }
  33. void Change(int rt, int op, int k)
  34. {
  35. if(op==3)///重新赋值,即再次初始化
  36. {
  37. a[rt].num = k%mod;
  38. a[rt].mul = 1;
  39. a[rt].add = 0;
  40. a[rt].op = 2;///重新赋值后子区间所有都重新覆盖
  41. }
  42. else if(op==2)
  43. {
  44. (a[rt].add *= k) %= mod;
  45. (a[rt].mul *= k) %= mod;
  46. (a[rt].num *= k) %= mod;
  47. }
  48. else
  49. {
  50. (a[rt].add += k) %= mod;
  51. (a[rt].num += k) %= mod;
  52. }
  53. }
  54.  
  55. void Up(int rt)
  56. {
  57. if(a[lson].op && a[rson].op)///若子区间为同数字区间且两子区间数字相同,
  58. if(a[lson].num == a[rson].num)///则可向上合并给父区间
  59. {
  60. a[rt].num = a[lson].num;
  61. a[rt].op = 1;
  62. }
  63. }
  64.  
  65. void Down(int rt)///向下的状态压缩,若不需此区间作答此区间暂时储存;
  66. { ///若需此区间作答则向下更新一层直到叶子节点
  67. if(a[rt].l != a[rt].r)
  68. {
  69. if(a[rt].op==2)
  70. {
  71. a[lson].num = a[rson].num = a[rt].num;
  72.  
  73. a[lson].op = a[rson].op = 2;
  74. a[lson].add = a[rson].add = 0;
  75. a[lson].mul = a[rson].mul = 1;
  76.  
  77. a[rt].add = 0;
  78. a[rt].mul = 1;
  79. a[rt].op = 1;
  80. }
  81.  
  82. if(a[rt].mul>1)///注意此处,先更新乘法,因为累乘会影响累加的状态
  83. {
  84. (a[lson].num *= a[rt].mul) %= mod;
  85. (a[lson].add *= a[rt].mul) %= mod;
  86. (a[lson].mul *= a[rt].mul) %= mod;
  87.  
  88. (a[rson].num *= a[rt].mul) %= mod;
  89. (a[rson].add *= a[rt].mul) %= mod;
  90. (a[rson].mul *= a[rt].mul) %= mod;
  91.  
  92. a[rt].mul = 1;
  93. }
  94.  
  95. if(a[rt].add)
  96. {
  97. (a[lson].num += a[rt].add) %= mod;
  98. (a[lson].add += a[rt].add) %= mod;
  99.  
  100. (a[rson].num += a[rt].add) %= mod;
  101. (a[rson].add += a[rt].add) %= mod;
  102.  
  103. a[rt].add = 0;
  104. }
  105. }
  106. }
  107. void Update(int rt, int op, int l, int r, int k)
  108. {
  109. if(a[rt].l==l && a[rt].r==r && a[rt].op)///找到数字相同区间
  110. {
  111. Change(rt, op, k);///执行操作
  112. return ;
  113. }
  114.  
  115. Down(rt);
  116. a[rt].op = 0;///假设默认区间数字已改变,标记为不同。
  117.  
  118. int mid = (a[rt].l + a[rt].r)/2;
  119. if(mid>=r)Update(lson, op, l, r, k);
  120. else if(mid<l)Update(rson, op, l, r, k);
  121. else
  122. {
  123. Update(lson, op, l, mid, k);
  124. Update(rson, op, mid+1, r, k);
  125. }
  126.  
  127. Up(rt);///执行操作后向上回溯,用已得到的子区间反馈负区间的状态
  128. }
  129. int Query(int rt, int l, int r, int p)
  130. {
  131. if(a[rt].l==l && a[rt].r==r && a[rt].op)///找到同数字区间即可计算
  132. {
  133. int ans = 1;
  134. for(int i=1; i<=p; i++)///一个p次方
  135. (ans *= a[rt].num) %= mod;
  136. ans = (ans * a[rt].len())%mod; ///区间内所有p次方
  137. return ans;
  138. }
  139.  
  140. Down(rt);
  141.  
  142. int mid = (a[rt].l + a[rt].r)/2;
  143.  
  144. if(mid>=r)return Query(lson, l, r, p);
  145. else if(mid<l)return Query(rson, l, r, p);
  146. else
  147. {
  148. int lans = Query(lson, l, mid, p);
  149. int rans = Query(rson, mid+1, r, p);
  150. return (lans+rans)%mod;
  151. }
  152. }
  153. int main()
  154. {
  155. int n, m;
  156. while(scanf("%d %d", &n, &m), m+n)
  157. {
  158. build(1, n, 1);
  159. int op, l, r, k;
  160. while(m--)
  161. {
  162. scanf("%d %d %d %d", &op, &l, &r, &k);
  163. if(op!=4)Update(1, op, l, r, k);///只要不为4都是更新操作
  164. else printf("%d\n", Query(1, l, r, k));
  165. }
  166. }
  167. return 0;
  168. }

HDU 4578 Transformation (线段树区间多种更新)的更多相关文章

  1. hdu 4578 Transformation 线段树多种操作裸题

    自己写了一个带结构体的WA了7.8次 但是测了几组小数据都对..感觉问题应该出在模运算那里.写完这波题解去对拍一下. 以后线段树绝不写struct!一般的struct都带上l,r 但是一条线段的长度确 ...

  2. HDU 4578 Transformation --线段树,好题

    题意: 给一个序列,初始全为0,然后有4种操作: 1. 给区间[L,R]所有值+c 2.给区间[L,R]所有值乘c 3.设置区间[L,R]所有值为c 4.查询[L,R]的p次方和(1<=p< ...

  3. hdu 4578 Transformation 线段树

    没什么说的裸线段树,注意细节就好了!!! 代码如下: #include<iostream> #include<stdio.h> #include<algorithm> ...

  4. hdu 4031 attack 线段树区间更新

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Subm ...

  5. hdu 5475 An easy problem(暴力 || 线段树区间单点更新)

    http://acm.hdu.edu.cn/showproblem.php?pid=5475 An easy problem Time Limit: 8000/5000 MS (Java/Others ...

  6. HDU 3308 LCIS (线段树&#183;单点更新&#183;区间合并)

    题意  给你一个数组  有更新值和查询两种操作  对于每次查询  输出相应区间的最长连续递增子序列的长度 基础的线段树区间合并  线段树维护三个值  相应区间的LCIS长度(lcis)  相应区间以左 ...

  7. HDU 3308 LCIS (线段树区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...

  8. hdu 4747【线段树-成段更新】.cpp

    题意: 给出一个有n个数的数列,并定义mex(l, r)表示数列中第l个元素到第r个元素中第一个没有出现的最小非负整数. 求出这个数列中所有mex的值. 思路: 可以看出对于一个数列,mex(r, r ...

  9. hdu 5023(线段树区间染色,统计区间内颜色个数)

    题目描述:区间染色问题,统计给定区间内有多少种颜色? 线段树模板的核心是对标记的处理 可以记下沿途经过的标记,到达目的节点之后一块算,也可以更新的时候直接更新到每一个节点 Lazy操作减少修改的次数( ...

随机推荐

  1. 第一节:简单的请求(Requests)和响应(Responses)

    目录 创建项目 开发服务器 创建名称为Polls的应用 编写你的第一个视图 创建项目 在命令行中,使用cd命令进入到你想要存储你的项目的目录,然后运行下面的命令: $ django-admin sta ...

  2. IOS开发-本地通知

    // 注册 发送通知的方法 -(void)pushNotfation{ //--------------初始化本地通知 alloc init 虽然是UI控件 但继承NSObject UILocalNo ...

  3. 一加3,CM13蓝牙共享互联网 无效。

    一加3准备把4G网络共享给魅族PRO5. 但在一加3的蓝牙设置里怎么勾选都无用. 最后发现在要在PRO5上设置才行. 1.在蓝牙列表中,点击带圈的感叹号. 2.选择“互联网访问”. - --

  4. 圆内接三角形(X神的代码玩的真好)

    设$S$为半径等于$1$的圆内接三角形的面积,则$4S+\dfrac 9S$的最小值是_______. [分析与解] 先证明$S$的最大值为$\dfrac{3\sqrt 3}4$.设$\triangl ...

  5. jquery判断复选框checkbox是否被选中

    jquery判断复选框checkbox是否被选中 使用is方法 //如果选中返回true //如果未选中返回false .is(':checked');

  6. Objective-C语法之KVO的使用

    简介: 上篇我们讲到了KVC,这篇我们学习KVO,全名为:Key Value Observing,直译为:基于键值的观察者. 那它有什么用呢?KVO主要用于视图交互方面,比如界面的某些数据变化了,界面 ...

  7. 28. Triangle && Pascal's Triangle && Pascal's Triangle II

    Triangle Given a triangle, find the minimum path sum from top to bottom. Each step you may move to a ...

  8. Testin云测试平台初体验

    这几天偶然接触到了一个叫做Testin的云测试平台,经过一番体验,感觉还是不错的,因为里面提供了大量的测试机型,可以针对Android手机的严重碎片化现象做出比较全面的测试,同时Testin的测试内容 ...

  9. 如何用js刷新aspxgridviw

    //写在js中 ASPxGridView1.Refresh();

  10. 【Tree 3】树形结构数据加载的思考

    前面两篇文章,分别介绍了使用递归和非递归算法加载树形结构数据的方式,本篇文章,则是自己闲下来的时候,进行的一点小思考. 一.什么地方会用到树形结构 刚开始一看到这种结构的时候,最先是想到了家谱.家谱就 ...