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. Unity Shader——Writing Surface Shaders(2)——Custom Lighting models in Surface Shaders

    Surface Shader中的自定义光照模型 当你在编写 Surface Shaders 时,是在描述一个表面的属性(反射颜色.法线……),而且光的交互过程是由一个光照模型来计算的.内建的光照模型有 ...

  2. java mvc web 项目web.xml头改错了,死活加载不上springMvc的jar

    Description    Resource    Path    Location    TypeOne or more constraints have not been satisfied.  ...

  3. 解决php的“It is not safe to rely on the system’s timezone settings”问题

    PHP调试的时候出现了警告: It is not safe to rely on the system解决方法,其实就是时区设置不正确造成的,本文提供了3种方法来解决这个问题. 实 际上,从PHP 5 ...

  4. [家里蹲大学数学杂志]第432期Hardy type inequalities

    If $p>1$, $f\geq 0$, and $$\bex F(x)=\int_0^x f(t)\rd t, \eex$$ then $$\bee\label{Hardy:0 to x} \ ...

  5. Angular(2)

    1.自定义指令,直接栗子: note:定义指定是驼峰,2部分 前缀+作用,but  调用 改驼峰首字母大写处为 (-首字母小写) <!DOCTYPE html><html lang= ...

  6. boost::asio::socket tcp 连接 在程序结束时崩溃。

    刚开始的时候一直不知道怎么回事,不过幸好我有在每个class 的析构时都打印一条信息. 这个时候发现我的一个tcp_connection (就是自定义的一个连接类) 在最后才被析构. 所以感觉这里可能 ...

  7. ThinkPHP 3.2.3集成uploadify上传控件

    uploadify控件有一个坑爹的问题,就是文件上传时会session丢失,官方解释http://www.uploadify.com/documentation/uploadify/using-ses ...

  8. Navicat链接Oracle提示ORA-12737

    ORA-12737: Instant Client Light: unsupported server character set string Cause: The character set sp ...

  9. ios delegate你必须知道的事情

    在我们的class中设计delegate的时候,我们通常会有几个注意事项. 假设我的class叫做MyClass,那我们可能会有定义一个MyClassDelegate这个protocol当作我的del ...

  10. 1,SFDC 管理员篇 - 基本设置

    1, 公司配置 Setup | Administrator| Company Profile *Company Inforamtion:公司基础信息,License信息,重要的设置包括本地时间,币种, ...