[关闭]
@Gary-Ying 2018-09-06T16:21:50.000000Z 字数 1443 阅读 1392

luo3372线段树模板的分块做法

解题报告


题目大意

请你维护一个有n个元素的整数序列,要求支持区间查询&区间修改

对于100%的数据,

分析

正常做法是线段树维护区间修改、区间查询,今天我要讲的是一种暴力做法:分块

分块的思想并不复杂,分块把一个长度为n的区间分成num段,操作时如果是整段用标记修改,不是整段的部分暴力修改

分析时间复杂度:在这题中,每段的标记修改是的,最多有num段,整段标记修改所用时间是的;不是整段的部分最多有个,暴力修改所用的时间是的;所以总时间是

根据基本不等式,num取时该式有最小值;所以num取

实现

分块的思想并不复杂,时间复杂度也不玄学,但是实现起来并不方便(可能是我弱)

分块的修改/查询都分为2部分:
1. 整块的修改
2. “零头”的修改

整块的修改是否简便:add[i] += val;
“零头”的修改直接修改,同时不要忘了维护所在块的信息:

  1. a[i] += val;
  2. sum[id[i]] += val;

修改就愉快地解决了,查询和修改差不多。

完整代码

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<cmath>
  5. using namespace std;
  6. const int maxn = 100007;
  7. int n, m, num, id[maxn];
  8. long long sum[1000], add[1000], a[maxn];
  9. int main(){
  10. scanf("%d%d", &n, &m);
  11. num = sqrt(n);
  12. for (int i = 1; i <= n; ++i){
  13. scanf("%lld", &a[i]);
  14. id[i] = (i-1) / num;
  15. sum[id[i]] += a[i];
  16. }
  17. while (m--){
  18. int d; scanf("%d", &d);
  19. if (d==1){
  20. int x, y, C; scanf("%d%d%d", &x, &y, &C);
  21. int Leftid = (x-1) / num + 1;
  22. int Rightid = (y-1) / num - 1;
  23. long long res = 0;
  24. for (int i = Leftid; i <= Rightid; ++i)
  25. add[i] += C;
  26. for (int i = x; i <= Leftid * num; ++i)
  27. a[i] += C, sum[id[i]] += C;
  28. for (int i = (Rightid+1)*num+1; i <= y; ++i)
  29. a[i] += C, sum[id[i]] += C;
  30. }else{
  31. int x, y; scanf("%d%d", &x, &y);
  32. int Leftid = (x-1) / num + 1;
  33. int Rightid = (y-1) / num - 1;
  34. if (id[x] == id[y]){
  35. long long res = 0;
  36. for (int i = x; i <= y; ++i)
  37. res += a[i] + add[id[i]];
  38. printf("%lld\n", res);
  39. continue;
  40. }
  41. long long res = 0;
  42. for (int i = Leftid; i <= Rightid; ++i)
  43. res += sum[i] + add[i] * num;
  44. for (int i = x; i <= Leftid * num; ++i)
  45. res += a[i] + add[Leftid-1];
  46. for (int i = (Rightid+1)*num+1; i <= y; ++i)
  47. res += a[i] + add[Rightid+1];
  48. printf("%lld\n", res);
  49. }
  50. }
  51. return 0;
  52. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注