题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578

Problem Description
Yuanfang is puzzled with the question below: 
There are n integers, a1, a2, …, an. The initial values of them are 0. There are four kinds of operations.
Operation 1: Add c to each number between ax and ay inclusive. In other words, do transformation ak<---ak+c, k = x,x+1,…,y.
Operation 2: Multiply c to each number between ax and ay inclusive. In other words, do transformation ak<---ak×c, k = x,x+1,…,y.
Operation 3: Change the numbers between ax and ay to c, inclusive. In other words, do transformation ak<---c, k = x,x+1,…,y.
Operation 4: Get the sum of p power among the numbers between ax and ay inclusive. In other words, get the result of axp+ax+1p+…+ay p.
Yuanfang has no idea of how to do it. So he wants to ask you to help him. 
 
Input
There are no more than 10 test cases.
For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000.
Each the following m lines contains an operation. Operation 1 to 3 is in this format: "1 x y c" or "2 x y c" or "3 x y c". Operation 4 is in this format: "4 x y p". (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3)
The input ends with 0 0.
 
Output
For each operation 4, output a single integer in one line representing the result. The answer may be quite large. You just need to calculate the remainder of the answer when divided by 10007.
 
Sample Input
5 5
3 3 5 7
1 2 4 4
4 1 5 2
2 2 5 8
4 3 5 3
0 0
 
Sample Output
307
7489

题意:

给出一个序列,有下列操作:

  1. 对区间[x,y]全部加上c
  2. 对区间[x,y]全部乘上c
  3. 将区间[x,y]全部改成c
  4. 查询区间[x,y]的p次方和

题解:

加强版的线段树,需要三个lazy标记,一个add表示加法标记,一个mul表示乘法标记,一个alt表示修改标记,

同时由于p=1,2,3,所以可以有三个val值:sum1表示一次方和,sum2表示平方和,sum3表示立方和,

然后我们要确定三个标记的优先级:alt第一,mul第二,add第三,pushdown的时候要按照这样的顺序pushdown,

同时下压高优先级的标记,会影响到低优先级的标记,这个需要注意,

另外,在接收到父节点传过来的add标记时,更新自身时(update_add成员函数),要注意计算sum3,sum2,sum1的先后顺序,一定是sum3,sum2,sum1,

这三个sum计算的方法如下:

$\begin{array}{l} \left( {a + x} \right)^2 = a^2 + 2ax + x^2 \\ \left( {a_1 + x} \right)^2 + \left( {a_2 + x} \right)^2 + \cdots + \left( {a_n + x} \right)^2 = \left( {a_1 ^2 + \cdots + a_n ^2 } \right) + 2x\left( {a_1 + \cdots + a_n } \right) + nx^2 \\ \left( {a + x} \right)^3 = a^3 + 3a^2 x + 3ax^2 + x^3 \\ \left( {a_1 + x} \right)^3 + \left( {a_2 + x} \right)^3 + \cdots + \left( {a_n + x} \right)^3 = \left( {a_1 ^3 + \cdots + a_n ^3 } \right) + 3x\left( {a_1 ^2 + \cdots + a_n ^2 } \right) + 3x^2 \left( {a_1 + \cdots + a_n } \right) + nx^3 \\ \end{array}$

AC代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int maxn=+;
  5. const int MOD=;
  6.  
  7. int n,m;
  8.  
  9. /********************************* Segment Tree - st *********************************/
  10. struct Node
  11. {
  12. int l,r;
  13. int sum1,sum2,sum3;
  14. int add,mul,alt;
  15. void Update_Alt(int x)
  16. {
  17. x%=MOD;
  18. sum1 = (r-l+) * x % MOD;
  19. sum2 = (r-l+) * x % MOD * x % MOD;
  20. sum3 = (r-l+) * x % MOD * x % MOD * x % MOD;
  21. alt=x;
  22. add=;
  23. mul=;
  24. }
  25. void Update_Mul(int x)
  26. {
  27. x%=MOD;
  28. sum1 = sum1 % MOD * x % MOD;
  29. sum2 = sum2 % MOD * x % MOD * x % MOD;
  30. sum3 = sum3 % MOD * x % MOD * x % MOD * x % MOD;
  31. mul = mul % MOD * x % MOD;
  32. add = add % MOD * x % MOD;
  33. }
  34. void Update_Add(int x)
  35. {
  36. x%=MOD;
  37. sum3 = ( sum3%MOD + *x%MOD*sum2%MOD + *x%MOD*x%MOD*sum1%MOD + (r-l+)*x%MOD*x%MOD*x%MOD ) % MOD;
  38. sum2 = ( sum2%MOD + *x%MOD*sum1%MOD + (r-l+)%MOD*x%MOD*x%MOD ) % MOD;
  39. sum1 = ( sum1%MOD + (r-l+)%MOD*x%MOD ) % MOD;
  40. add=(add%MOD+x)%MOD;
  41. }
  42. }node[*maxn];
  43. void Pushdown(int root)
  44. {
  45. int ls=root*, rs=root*+;
  46. if(node[root].alt!=)
  47. {
  48. node[ls].Update_Alt(node[root].alt);
  49. node[rs].Update_Alt(node[root].alt);
  50. node[root].alt=;
  51. }
  52. if(node[root].mul!=)
  53. {
  54. node[ls].Update_Mul(node[root].mul);
  55. node[rs].Update_Mul(node[root].mul);
  56. node[root].mul=;
  57. }
  58. if(node[root].add!=)
  59. {
  60. node[ls].Update_Add(node[root].add);
  61. node[rs].Update_Add(node[root].add);
  62. node[root].add=;
  63. }
  64. }
  65. void Pushup(int root)
  66. {
  67. int ls=root*, rs=root*+;
  68. node[root].sum1=(node[ls].sum1+node[rs].sum1)%MOD;
  69. node[root].sum2=(node[ls].sum2+node[rs].sum2)%MOD;
  70. node[root].sum3=(node[ls].sum3+node[rs].sum3)%MOD;
  71. }
  72. void Build(int root,int l,int r) //对区间[l,r]建树
  73. {
  74. if(l>r) return;
  75. node[root].l=l; node[root].r=r;
  76. node[root].sum1=;
  77. node[root].sum2=;
  78. node[root].sum3=;
  79. node[root].alt=;
  80. node[root].add=;
  81. node[root].mul=;
  82.  
  83. if(l<r)
  84. {
  85. int mid=l+(r-l)/;
  86. Build(root*,l,mid);
  87. Build(root*+,mid+,r);
  88. Pushup(root);
  89. }
  90. }
  91. void Alt(int root,int st,int ed,ll val) //区间[st,ed]全部改成val
  92. {
  93. if(st>node[root].r || ed<node[root].l) return;
  94. if(st<=node[root].l && node[root].r<=ed) node[root].Update_Alt(val);
  95. else
  96. {
  97. Pushdown(root);
  98. Alt(root*,st,ed,val);
  99. Alt(root*+,st,ed,val);
  100. Pushup(root);
  101. }
  102. }
  103. void Mul(int root,int st,int ed,ll val) //区间[st,ed]全部加上val
  104. {
  105. if(st>node[root].r || ed<node[root].l) return;
  106. if(st<=node[root].l && node[root].r<=ed) node[root].Update_Mul(val);
  107. else
  108. {
  109. Pushdown(root);
  110. Mul(root*,st,ed,val);
  111. Mul(root*+,st,ed,val);
  112. Pushup(root);
  113. }
  114. }
  115. void Add(int root,int st,int ed,ll val) //区间[st,ed]全部加上val
  116. {
  117. if(st>node[root].r || ed<node[root].l) return;
  118. if(st<=node[root].l && node[root].r<=ed) node[root].Update_Add(val);
  119. else
  120. {
  121. Pushdown(root);
  122. Add(root*,st,ed,val);
  123. Add(root*+,st,ed,val);
  124. Pushup(root);
  125. }
  126. }
  127. int Query(int root,int st,int ed,int p) //查询区间[st,ed]的p次方和
  128. {
  129. if(st>node[root].r || ed<node[root].l) return ;
  130. if(st<=node[root].l && node[root].r<=ed)
  131. {
  132. if(p==) return node[root].sum1;
  133. if(p==) return node[root].sum2;
  134. if(p==) return node[root].sum3;
  135. }
  136. else
  137. {
  138. Pushdown(root);
  139. int ls=Query(root*,st,ed,p)%MOD;
  140. int rs=Query(root*+,st,ed,p)%MOD;
  141. Pushup(root);
  142. return (ls+rs)%MOD;
  143. }
  144. }
  145. /********************************* Segment Tree - st *********************************/
  146.  
  147. int main()
  148. {
  149. while(scanf("%d%d",&n,&m) && n*m!=)
  150. {
  151. Build(,,n);
  152. for(int i=;i<=m;i++)
  153. {
  154. int op; scanf("%d",&op);
  155. if(op==)
  156. {
  157. int x,y,k;
  158. scanf("%d%d%d",&x,&y,&k);
  159. Add(,x,y,k);
  160. }
  161. if(op==)
  162. {
  163. int x,y,k;
  164. scanf("%d%d%d",&x,&y,&k);
  165. Mul(,x,y,k);
  166. }
  167. if(op==)
  168. {
  169. int x,y,k;
  170. scanf("%d%d%d",&x,&y,&k);
  171. Alt(,x,y,k);
  172. }
  173. if(op==)
  174. {
  175. int l,r,p;
  176. scanf("%d%d%d",&l,&r,&p);
  177. printf("%d\n",Query(,l,r,p));
  178. }
  179. }
  180. }
  181. }

HDU 4578 - Transformation - [加强版线段树]的更多相关文章

  1. HDU 4578 Transformation (线段树)

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others)T ...

  2. HDU 4578——Transformation——————【线段树区间操作、确定操作顺序】

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others)T ...

  3. HDU - 4578 Transformation(线段树区间修改)

    https://cn.vjudge.net/problem/HDU-4578 题意 4种操作,区间加,区间乘,区间变为一个数,求区间的和.平方和以及立方和. 分析 明显线段树,不过很麻烦..看kuan ...

  4. HDU 4578 Transformation (线段树区间多种更新)

    http://acm.hdu.edu.cn/showproblem.php?pid=4578 题目大意:对于一个给定序列,序列内所有数的初始值为0,有4种操作.1:区间(x, y)内的所有数字全部加上 ...

  5. hdu 4578 Transformation(线段树)

    线段树上的多操作... 题目大意: 树上 的初始值为0,然后有下列三种操作和求和. 1  x y c  在X-Y的之间全部加上C. 2  x y c  在X-Y的之间全部乘上C. 3  x y c   ...

  6. Hdu 4578 Transformation (线段树 分类分析)

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others)T ...

  7. hdu 5700区间交(线段树)

    区间交 Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...

  8. Snacks HDU 5692 dfs序列+线段树

    Snacks HDU 5692 dfs序列+线段树 题意 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充, ...

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

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

随机推荐

  1. Simply Syntax(思维)

    Simply Syntax Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5551   Accepted: 2481 Des ...

  2. C++实现按1的个数排序

    题目内容:有一些0.1字符串,将其按1的个数的多少的顺序进行输出. 输入描述:本题只有一组测试数据.输入数据由若干数字组成,它是由若干个0和1组成的数字. 输出描述:对所有输入的数据,按1的个数进行生 ...

  3. Visual Studio 添加SVN插件

    这两天为了开发一个移动混合式的框架,被迫去学习去使用VisualStudio,这玩意当年离开校园就再也没用过了,再次看到感觉还是很眼熟...,这篇文件就简单说明下VS下怎么安装SVN插件吧: 1 首先 ...

  4. js中对象的深度复制

    // 对象的深度复制 cloneObj(oldObj) var cloneObj = function (obj) { var newObj = {}; if (obj instanceof Arra ...

  5. 第一个map reduce程序

    完成了第一个mapReduce例子,记录一下. 实验环境: hadoop在三台ubuntu机器上部署 开发在window7上进行 hadoop版本2.2.0 下载了hadoop-eclipse-plu ...

  6. Splash scroll_position 属性

    scroll_position属性用于控制页面上下或左右滚动,如下,表示控制页面向下滚动 400 像素值并返回结果图, function main(splash, args) assert(splas ...

  7. js数组sort方法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. flask实现简单的接收json返回json的接口

    结合http://docs.jinkan.org/docs/flask/quickstart.html#a-minimal-application这个flask文档实现 #!/usr/bin/pyth ...

  9. OAuth网络协议(转)

    一.应用场景 为了理解OAuth的适用场合,让我举一个假设的例子. 有一个"云冲印"的网站,可以将用户储存在Google的照片,冲印出来.用户为了使用该服务,必须让"云冲 ...

  10. -webkit-transition -moz-transition transition

    -webkit-transition  -moz-transition transition 可以定义动画的变化时间曲线-webkit-transition-timing-function: ease ...