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

题意:给定一个长度为n的序列,有m次操作。操作有3种:

1 l,r :区间[l,r]的值变成phi[val[i]](l<=i<=r; phi是欧拉值)

2 l,r,x:区间[l,r]的值变成x

3 l,r:求区间[l,r]的和

思路:操作2和3就是传统的简单线段树,操作2对应区间覆盖,操作3对应区间求和,重点在于操作1,由于一个数经过不超过log次求phi后会变成1,所以可以在线段树是用一个same标记,如果整个区间的数都相同则操作1就转换成操作2的区间覆盖了。如果操作的区间[l,r]已经包含住当前递归的子树区间但是子树的same标记为假则继续递归到子树的same标记为真为止,最多递归到叶子结点。

  1. #define _CRT_SECURE_NO_DEPRECATE
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<algorithm>
  6. #include<string>
  7. #include<queue>
  8. #include<vector>
  9. #include<time.h>
  10. #include<cmath>
  11. using namespace std;
  12. typedef long long int LL;
  13. #define L(k)(k<<1)
  14. #define R(k)(k<<1|1)
  15. const LL INF = ;
  16. const int MAXN = 3e5 + ;
  17. const int MAXX = 1e7 + ;
  18. struct Node{
  19. int l, r, val;
  20. LL sum;
  21. bool same;
  22. Node(int _l = , int _r = , int _val = , LL _sum = , bool _same = false){
  23. l = _l; r = _r; sum = _sum; same = _same; val = _val;
  24. }
  25. }Seg[MAXN * ];
  26. int val[MAXN], Phi[MAXX];
  27. void pushUp(int k){
  28. Seg[k].sum = Seg[L(k)].sum + Seg[R(k)].sum;
  29. if (Seg[L(k)].val == Seg[R(k)].val&&Seg[L(k)].same&&Seg[R(k)].same&&Seg[L(k)].val != -){
  30. Seg[k].same = true;
  31. Seg[k].val = Seg[L(k)].val;
  32. }
  33. else{
  34. Seg[k].same = false;
  35. Seg[k].val = -;
  36. }
  37. }
  38. void pushDown(int k){
  39. if (Seg[k].same){
  40. Seg[L(k)].same = Seg[R(k)].same = true;
  41. Seg[L(k)].val = Seg[R(k)].val = Seg[k].val;
  42. Seg[L(k)].sum = 1LL * (Seg[L(k)].r - Seg[L(k)].l + )*Seg[L(k)].val;
  43. Seg[R(k)].sum = 1LL * (Seg[R(k)].r - Seg[R(k)].l + )*Seg[R(k)].val;
  44. }
  45. }
  46. void Build(int st, int ed, int k){
  47. Seg[k].l = st; Seg[k].r = ed; Seg[k].same = false; Seg[k].val = -;
  48. if (st == ed){
  49. Seg[k].val = val[st];
  50. Seg[k].sum = val[st];
  51. Seg[k].same = true;
  52. return;
  53. }
  54. int mid = (st + ed) >> ;
  55. Build(st, mid, L(k)); Build(mid + , ed, R(k));
  56. pushUp(k);
  57. }
  58. void Change(int st, int ed, int val, int k){
  59. if (Seg[k].l == st&&Seg[k].r == ed){
  60. Seg[k].same = true;
  61. Seg[k].val = val;
  62. Seg[k].sum = 1LL * (ed - st + )*val;
  63. return;
  64. }
  65. pushDown(k);
  66. if (Seg[L(k)].r >= ed){
  67. Change(st, ed, val, L(k));
  68. }
  69. else if (Seg[R(k)].l <= st){
  70. Change(st, ed, val, R(k));
  71. }
  72. else{
  73. Change(st, Seg[L(k)].r, val, L(k));
  74. Change(Seg[R(k)].l, ed, val, R(k));
  75. }
  76. pushUp(k);
  77. }
  78. void Modify(int st, int ed, int k){
  79. if (Seg[k].l == st&&Seg[k].r == ed&&Seg[k].same){
  80. Seg[k].val = Phi[Seg[k].val];
  81. Seg[k].sum = 1LL * (ed - st + )*Seg[k].val;
  82. return;
  83. }
  84. pushDown(k);
  85. if (Seg[L(k)].r >= ed){
  86. Modify(st, ed, L(k));
  87. }
  88. else if (Seg[R(k)].l <= st){
  89. Modify(st, ed, R(k));
  90. }
  91. else{
  92. Modify(st, Seg[L(k)].r, L(k));
  93. Modify(Seg[R(k)].l, ed, R(k));
  94. }
  95. pushUp(k);
  96. }
  97. LL Query(int st, int ed, int k){
  98. if (Seg[k].l == st&&Seg[k].r == ed){
  99. return Seg[k].sum;
  100. }
  101. pushDown(k);
  102. if (Seg[L(k)].r >= ed){
  103. return Query(st, ed, L(k));
  104. }
  105. else if (Seg[R(k)].l <= st){
  106. return Query(st, ed, R(k));
  107. }
  108. else{
  109. return Query(st, Seg[L(k)].r, L(k)) + Query(Seg[R(k)].l, ed, R(k));
  110. }
  111. pushUp(k);
  112. }
  113. void GetPhi(){ //预处理欧拉值
  114. memset(Phi, , sizeof(Phi));
  115. Phi[] = ;
  116. for (LL i = ; i < MAXX; i++){
  117. if (!Phi[i]){
  118. for (LL j = i; j < MAXX; j += i){
  119. if (!Phi[j]) Phi[j] = j;
  120. Phi[j] = Phi[j] / i*(i - );
  121. }
  122. }
  123. }
  124. }
  125. int main(){
  126. //#ifdef kirito
  127. // freopen("in.txt", "r", stdin);
  128. // freopen("out.txt", "w", stdout);
  129. //#endif
  130. // int start = clock();
  131. int n, t, m; GetPhi();
  132. scanf("%d", &t);
  133. while (t--){
  134. scanf("%d%d", &n, &m);
  135. for (int i = ; i <= n; i++){
  136. scanf("%d", &val[i]);
  137. }
  138. Build(, n, );
  139. for (int i = ; i <= m; i++){
  140. int tpe, l, r, x;
  141. scanf("%d%d%d", &tpe, &l, &r);
  142. if (tpe == ){
  143. Modify(l, r, );
  144. }
  145. else if (tpe == ){
  146. scanf("%d", &x);
  147. Change(l, r, x, );
  148. }
  149. else{
  150. printf("%lld\n", Query(l, r, ));
  151. }
  152. }
  153. }
  154. //#ifdef LOCAL_TIME
  155. // cout << "[Finished in " << clock() - start << " ms]" << endl;
  156. //#endif
  157. return ;
  158. }

HDU 5634 线段树的更多相关文章

  1. hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  2. hdu 3974 线段树 将树弄到区间上

    Assign the task Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  3. hdu 3436 线段树 一顿操作

    Queue-jumpers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  4. hdu 3397 线段树双标记

    Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  5. hdu 4578 线段树(标记处理)

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

  6. hdu 4533 线段树(问题转化+)

    威威猫系列故事——晒被子 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tot ...

  7. hdu 2871 线段树(各种操作)

    Memory Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  8. hdu 4052 线段树扫描线、奇特处理

    Adding New Machine Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  9. hdu 1542 线段树扫描(面积)

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

随机推荐

  1. VS2017 IDE 说明

  2. SQL Server 中用While循环替代游标Cursor的解决方案

    在编写SQL批处理或存储过程代码的过程中,经常会碰到有些业务逻辑的处理,需要对满足条件的数据记录逐行进行处理,这个时候,大家首先想到的方案大部分是用“游标”进行处理. 举个例子,在订单管理系统中,客服 ...

  3. Python3解leetcode Path Sum III

    问题描述: You are given a binary tree in which each node contains an integer value. Find the number of p ...

  4. 使用WebAPI流式传输大文件(在IIS上大于2GB)

    这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时候,向后端传入参数:当前为第几块文件,和分片总数 下面直接贴代码吧,一些难懂的我大部分都加上注释了: 上传文件实体类: 看得 ...

  5. MySQL系统服务的安装删除

    1.从该地址http://dev.mysql.com/downloads/mysql/中选择windows的版本,选择下载. 2.将下载的压缩包解压. 3.将根目录下的my-default.ini复制 ...

  6. 和风api爬取天气预报数据

    ''' 和风api爬取天气预报数据 目标:https://free-api.heweather.net/s6/weather/forecast?key=cc33b9a52d6e48de85247779 ...

  7. ArayList的一些常用法<一> 转

    转:http://yy.azj.blog.163.com/blog/static/18508700320122893451389/ import java.util.ArrayList; import ...

  8. HDU6599:求本质不同的子串(回文串)长度及数量

    目录 hdu6599题意: manacher+后缀自动机+倍增 \(O(nlog(n))\) manacher+后缀数组+二分 \(O(nlog(n))\) 回文树(回文自动机) \(O(n)\) @ ...

  9. 洛谷P2661 信息传递(最小环,并查集)

    洛谷P2661 信息传递 最小环求解采用并查集求最小环. 只适用于本题的情况.对于新加可以使得两个子树合并的边,总有其中一点为其中一棵子树的根. 复杂度 \(O(n)\) . #include< ...

  10. SVN 忽略添加文件和文件夹

    你添加的文件和文件夹是没有加入版本控制的,是你新添加的,接下来的设置才有用 忽略这个文件的方式有两种 第一种方式 添加svn:ignore    右键文件-->TortoiseSvn--> ...