题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578  , 线段树的区间更新 + 多种操作,好题。

  虽然是比较裸的线段树,但是比较麻烦,并且有很多细节需要考虑,最后我7.3s很惊险地过了,求大神告知优化方法。


  这道题坑在有三种询问:set , add , mul。所以lazy标记要有三个,如果三个标记同时出现的处理方法——当更新set操作时,就把add标记和mul标记全部取消;当更新mul操作时,如果当前节点add标记存在,就把add标记改为:add * mul。这样的话就可以在PushDown()操作中先执行set,然后mul,最后add。

  麻烦在有三种询问:和 , 平方和 , 立方和。对于set和mul操作来说,这三种询问都比较好弄。

  对于add操作,和的话就比较好弄,按照正常方法就可以;

  平方和这样来推:(a + c)2 = a2 + c2 + 2ac  , 即sum2[rt] = sum2[rt] + (r - l + 1) * c * c + 2 * sum1[rt] * c;

  立方和这样推:(a + c)3 = a3 + c3 + 3a(a2 + ac) , 即sum3[rt] = sum3[rt] + (r - l + 1) * c * c * c + 3 * c * (sum2[rt] + sum1[rt] * c);

  几个注意点:add标记取消的时候是置0,mul标记取消的时候是置1;在PushDown()中也也要注意取消标记,如set操作中取消add和mul,mul操作中更新add; 在add操作中要注意sum3 , sum2 , sum1的先后顺序,一定是先sum3 , 然后sum2 , 最后sum1; int容易爆,还是用LL要保险一点; 最后就是运算较多,不要漏掉东西。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <vector>
  4. #include <cmath>
  5. #include <string>
  6. #include <string.h>
  7. #include <algorithm>
  8. using namespace std;
  9. #define LL __int64
  10. #define eps 1e-8
  11. #define INF INT_MAX
  12. #define lson l , m , rt << 1
  13. #define rson m + 1 , r , rt << 1 | 1
  14. const int MOD = ;
  15. const int maxn = + ;
  16. const int N = ;
  17. LL add[maxn << ] , set[maxn << ] , mul[maxn << ];
  18. LL sum1[maxn << ] , sum2[maxn << ] , sum3[maxn << ];
  19. void PushUp(int rt)
  20. {
  21. sum1[rt] = (sum1[rt << ] + sum1[rt << | ]) % MOD;
  22. sum2[rt] = (sum2[rt << ] + sum2[rt << | ]) % MOD;
  23. sum3[rt] = (sum3[rt << ] + sum3[rt << | ]) % MOD;
  24. }
  25. void build(int l , int r , int rt)
  26. {
  27. add[rt] = set[rt] = ;
  28. mul[rt] = ;
  29. if(l == r) {
  30. sum1[rt] = sum2[rt] = sum3[rt] = ;
  31. return;
  32. }
  33. int m = (l + r) >> ;
  34. build(lson);
  35. build(rson);
  36. PushUp(rt);
  37. }
  38. void PushDown(int rt , int len)
  39. {
  40. if(set[rt]) {
  41. set[rt << ] = set[rt << | ] = set[rt];
  42. add[rt << ] = add[rt << | ] = ; //注意这个也要下放
  43. mul[rt << ] = mul[rt << | ] = ;
  44. LL tmp = ((set[rt] * set[rt]) % MOD) * set[rt] % MOD;
  45. sum1[rt << ] = ((len - (len >> )) % MOD) * (set[rt] % MOD) % MOD;
  46. sum1[rt << | ] = ((len >> ) % MOD) * (set[rt] % MOD) % MOD;
  47. sum2[rt << ] = ((len - (len >> )) % MOD) * ((set[rt] * set[rt]) % MOD) % MOD;
  48. sum2[rt << | ] = ((len >> ) % MOD) * ((set[rt] * set[rt]) % MOD) % MOD;
  49. sum3[rt << ] = ((len - (len >> )) % MOD) * tmp % MOD;
  50. sum3[rt << | ] = ((len >> ) % MOD) * tmp % MOD;
  51. set[rt] = ;
  52. }
  53. if(mul[rt] != ) { //这个就是mul[rt] != 1 , 当时我这里没注意所以TLE了
  54. mul[rt << ] = (mul[rt << ] * mul[rt]) % MOD;
  55. mul[rt << | ] = (mul[rt << | ] * mul[rt]) % MOD;
  56. if(add[rt << ]) //注意这个也要下放
  57. add[rt << ] = (add[rt << ] * mul[rt]) % MOD;
  58. if(add[rt << | ])
  59. add[rt << | ] = (add[rt << | ] * mul[rt]) % MOD;
  60. LL tmp = (((mul[rt] * mul[rt]) % MOD * mul[rt]) % MOD);
  61. sum1[rt << ] = (sum1[rt << ] * mul[rt]) % MOD;
  62. sum1[rt << | ] = (sum1[rt << | ] * mul[rt]) % MOD;
  63. sum2[rt << ] = (sum2[rt << ] % MOD) * ((mul[rt] * mul[rt]) % MOD) % MOD;
  64. sum2[rt << | ] = (sum2[rt << | ] % MOD) * ((mul[rt] * mul[rt]) % MOD) % MOD;
  65. sum3[rt << ] = (sum3[rt << ] % MOD) * tmp % MOD;
  66. sum3[rt << | ] = (sum3[rt << | ] % MOD) * tmp % MOD;
  67. mul[rt] = ;
  68. }
  69. if(add[rt]) {
  70. add[rt << ] += add[rt]; //add是+= , mul是*=
  71. add[rt << | ] += add[rt];
  72. LL tmp = (add[rt] * add[rt] % MOD) * add[rt] % MOD; //注意sum3 , sum2 , sum1的先后顺序
  73. sum3[rt << ] = (sum3[rt << ] + (tmp * (len - (len >> )) % MOD) + * add[rt] * ((sum2[rt << ] + sum1[rt << ] * add[rt]) % MOD)) % MOD;
  74. sum3[rt << | ] = (sum3[rt << | ] + (tmp * (len >> ) % MOD) + * add[rt] * ((sum2[rt << | ] + sum1[rt << | ] * add[rt]) % MOD)) % MOD;
  75. sum2[rt << ] = (sum2[rt << ] + ((add[rt] * add[rt] % MOD) * (len - (len >> )) % MOD) + ( * sum1[rt << ] * add[rt] % MOD)) % MOD;
  76. sum2[rt << | ] = (sum2[rt << | ] + (((add[rt] * add[rt] % MOD) * (len >> )) % MOD) + ( * sum1[rt << | ] * add[rt] % MOD)) % MOD;
  77. sum1[rt << ] = (sum1[rt << ] + (len - (len >> )) * add[rt]) % MOD;
  78. sum1[rt << | ] = (sum1[rt << | ] + (len >> ) * add[rt]) % MOD;
  79. add[rt] = ;
  80. }
  81. }
  82. void update(int L , int R , int c , int ch , int l , int r , int rt)
  83. {
  84. if(L <= l && R >= r) {
  85. if(ch == ) {
  86. set[rt] = c;
  87. add[rt] = ;
  88. mul[rt] = ;
  89. sum1[rt] = ((r - l + ) * c) % MOD;
  90. sum2[rt] = ((r - l + ) * ((c * c) % MOD)) % MOD;
  91. sum3[rt] = ((r - l + ) * (((c * c) % MOD) * c % MOD)) % MOD;
  92. } else if(ch == ) {
  93. mul[rt] = (mul[rt] * c) % MOD;
  94. if(add[rt])
  95. add[rt] = (add[rt] * c) % MOD;
  96. sum1[rt] = (sum1[rt] * c) % MOD;
  97. sum2[rt] = (sum2[rt] * (c * c % MOD)) % MOD;
  98. sum3[rt] = (sum3[rt] * ((c * c % MOD) * c % MOD)) % MOD;
  99. } else if(ch == ) {
  100. add[rt] += c;
  101. LL tmp = (((c * c) % MOD * c) % MOD * (r - l + )) % MOD; //(r - l + 1) * c^3
  102. sum3[rt] = (sum3[rt] + tmp + * c * ((sum2[rt] + sum1[rt] * c) % MOD)) % MOD;
  103. sum2[rt] = (sum2[rt] + (c * c % MOD * (r - l + ) % MOD) + * sum1[rt] * c) % MOD;
  104. sum1[rt] = (sum1[rt] + (r - l + ) * c) % MOD;
  105. }
  106. return;
  107. }
  108. PushDown(rt , r - l + );
  109. int m = (l + r) >> ;
  110. if(L > m)
  111. update(L , R , c , ch , rson);
  112. else if(R <= m)
  113. update(L , R , c , ch , lson);
  114. else {
  115. update(L , R , c , ch , lson);
  116. update(L , R , c , ch , rson);
  117. }
  118. PushUp(rt);
  119. }
  120. LL query(int L , int R , int p , int l , int r , int rt)
  121. {
  122. if(L <= l && R >= r) {
  123. if(p == )
  124. return sum1[rt] % MOD;
  125. else if(p == )
  126. return sum2[rt] % MOD;
  127. else
  128. return sum3[rt] % MOD;
  129. }
  130. PushDown(rt , r - l + );
  131. int m = (l + r) >> ;
  132. if(L > m)
  133. return query(L , R , p , rson);
  134. else if(R <= m)
  135. return query(L , R , p , lson);
  136. else
  137. return (query(L , R , p , lson) + query(L , R , p , rson)) % MOD;
  138. }
  139. int main()
  140. {
  141. int n , m;
  142. int a , b , c , ch;
  143. while(~scanf("%d %d" , &n , &m))
  144. {
  145. if(n == && m == )
  146. break;
  147. build( , n , );
  148. while(m--) {
  149. scanf("%d %d %d %d" , &ch , &a , &b , &c);
  150. if(ch != ) {
  151. update(a , b , c , ch , , n , );
  152. } else {
  153. printf("%I64d\n" , query(a , b , c , , n , ));
  154. }
  155. }
  156. }
  157. return ;
  158. }

HDU4578 线段树(区间更新 + 多种操作)的更多相关文章

  1. HDU4578 线段树(区间更新 + 多种操作)和平方,立方

    参考:https://www.cnblogs.com/H-Vking/p/4297973.html 题意: 虽然是比较裸的线段树,但是比较麻烦,并且有很多细节需要考虑,对着别人的ac代码debug了一 ...

  2. hdu4578线段树区间更新

    /* 只有在区间中的数字不相同时才pushdown:往子区间传递数字再到子区间更新,同时该区间的flag置0 更新完左右子区间后进行pushup,如果左右子区间数字相同,那么把子区间合并,子区间数字置 ...

  3. hihoCoder 1080 : 更为复杂的买卖房屋姿势 线段树区间更新

    #1080 : 更为复杂的买卖房屋姿势 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho都是游戏迷,“模拟都市”是他们非常喜欢的一个游戏,在这个游戏里面他们 ...

  4. HDU 5023 A Corrupt Mayor's Performance Art(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色 ...

  5. HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是 ...

  6. HDU5039--Hilarity DFS序+线段树区间更新 14年北京网络赛

    题意:n个点的树,每个条边权值为0或者1, q次操作 Q 路径边权抑或和为1的点对数, (u, v)(v, u)算2个. M i修改第i条边的权值 如果是0则变成1, 否则变成0 作法: 我们可以求出 ...

  7. hihoCoder #1078 : 线段树的区间修改(线段树区间更新板子题)

    #1078 : 线段树的区间修改 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 对于小Ho表现出的对线段树的理解,小Hi表示挺满意的,但是满意就够了么?于是小Hi将问题 ...

  8. hdu 3966(树链剖分+线段树区间更新)

    传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...

  9. POJ 3468:A Simple Problem with Integers(线段树区间更新模板)

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

随机推荐

  1. sqlmap中##和$$的区别

    一. 主要区别 #a# //解析sqlmap配置文件时自动加单引号,即'a' $a$ //解析sqlmap配置文件时不加单引号,即a 如果传进来的条件需要order by的话,那一定用第二种 #是把传 ...

  2. oracle 如何查看已经创建好的触发器语句-select trigger_body from user_triggers where trigger_name='XXXX';

    使用trigge_body查询, select trigger_body from user_triggers where trigger_name='XXXX'; 如下图: SQL> sele ...

  3. Linux进程管理之“四大名捕”

    一.四大名捕 四大名捕,最初出现于温瑞安创作的武侠小说,是朝廷中正义力量诸葛小花的四大徒弟,四人各怀绝技,分别是轻功暗器高手“无情”.内功卓越的高手“铁手”.腿功惊人的“追命”和剑法一流的“冷血”本文 ...

  4. [转]OData and Authentication – Part 6 – Custom Basic Authentication

    本文转自:https://blogs.msdn.microsoft.com/astoriateam/2010/07/21/odata-and-authentication-part-6-custom- ...

  5. SQL Serever学习17——数据库的分析和设计

    数据库的分析和设计 设计数据库确定一个合适的数据模型,满足3个要求: 符合用户需求,包含用户所需的所有数据 能被数据库管理系统实现,如sqlserver,oracle,db2 具有比较高质量,容易理解 ...

  6. javascript的ajax功能的概念和示例

    AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML). 个人理解:ajax就是无刷新提交,然后得到返回内容. 对应的不使用ajax时的传统网 ...

  7. SOA(面向服务架构)——踩坑后反思:这样值得吗?

    SOA(面向服务架构)——踩坑后反思:这样值得吗?

  8. Cheatsheet: 2017 06.01 ~ 06.30

    .NET Porting a .NET Framework library to .NET Core Performance Improvements in .NET Core High-perfor ...

  9. Java CountDownLatch解析(上)

    写在前面的话 最近一直在边工作边学习分布式的东西,看到了构建Java中间件的基础知识,里面有提到Java多线程并发的工具类,例如ReentrantLock.CyclicBarrier.CountDow ...

  10. 让你跟上nodejs的资源

    For a long time, JavaScript developers hoped for a server-side solution that would allow them to ful ...