系列索引:

分块

阅:《「分块」数列分块入门 1-9 by hzwer》

树状数组 Binary Indexed Tree

时间复杂度 每次操作 \(O(\log n)\),空间复杂度 \(O(n)\)。

Pure

下标从 1 开始。

  1. ll t[N];
  2. inline int lowbit(int x) {return x&-x; }
  3. inline void update(int x, ll val) {
  4. for (; x<=n; x+=lowbit(x)) t[x]+=val;
  5. }
  6. inline ll sum(int x) {
  7. ll res=0;
  8. for (; x; x-=lowbit(x)) res+=t[x];
  9. return res;
  10. }

2 Dimensions

  1. void update(int x, int y, int z) {
  2. int i = x;
  3. while (i <= n) {
  4. int j = y;
  5. while (j <= m) {
  6. t[i][j] += z;
  7. j += lowbit(j);
  8. }
  9. i += lowbit(i);
  10. }
  11. }
  12. int sum(int x, int y) { // prefix
  13. int res = 0, i = x;
  14. while (i > 0) {
  15. int j = y;
  16. while (j > 0) {
  17. res += t[i][j];
  18. j -= lowbit(j);
  19. }
  20. i -= lowbit(i);
  21. }
  22. return res;
  23. }

线段树 Segment Tree

时间复杂度 每次操作 \(O(\log n)\),空间复杂度 \(O(4n)\)。

Standard

单点修改,区间求和:

  1. #define lson k<<1, l, mid
  2. #define rson k<<1|1, mid+1, r
  3. int t[N<<2];
  4. void modify(int k, int l, int r, int x) {
  5. if (l==r&&l==x) {++t[k]; return; }
  6. register int mid=l+r>>1;
  7. if (x<=mid) modify(lson, x);
  8. if (mid<x) modify(rson, x);
  9. ++t[k];
  10. }
  11. int query(int k, int l, int r, int x, int y) {
  12. if (x<=l&&r<=y) return t[k];
  13. register int mid=l+r>>1, res=0;
  14. if (x<=mid) res+=query(lson, x, y);
  15. if (mid<y) res+=query(rson, x, y);
  16. return res;
  17. }

区间修改,区间求和:

  1. ll t[N<<2], laz[N<<2];
  2. inline void add(int k, int l, int r, ll val) {
  3. laz[k]+=val;
  4. t[k]+=(r-l+1)*val;
  5. }
  6. inline void pd(int k, int l, int r, int mid) {
  7. if (!laz[k]) return;
  8. add(lson, laz[k]), add(rson, laz[k]);
  9. laz[k]=0;
  10. }
  11. void modify(int k, int l, int r, int x, int y, ll val) {
  12. if (x<=l&&r<=y) {add(k, l, r, val); return; }
  13. int mid=l+r>>1;
  14. pd(k, l, r, mid);
  15. if (x<=mid) modify(lson, x, y, val);
  16. if (mid<y) modify(rson, x, y, val);
  17. t[k]=t[k<<1]+t[k<<1|1];
  18. }
  19. ll query(int k, int l, int r, int x, int y) {
  20. if (x<=l&&r<=y) return t[k];
  21. int mid=l+r>>1; ll res=0;
  22. pd(k, l, r, mid);
  23. if (x<=mid) res+=query(lson, x, y);
  24. if (mid<y) res+=query(rson, x, y);
  25. return res;
  26. }

有运算优先级:如同时支持区间乘和区间加,将标记设计为先乘 a 再加 b,那么区间加时直接加 b 即可,而区间乘时需要将 a 和 b 都乘上一个数。

  1. int lazy[N<<2], sum[N<<2], lazy2[N<<2];
  2. void build(int k, int l, int r) {
  3. lazy2[k] = 1;
  4. if (l==r) { sum[k] = data[l]; return; }
  5. int mid = l+r >> 1;
  6. build(k<<1, l, mid);
  7. build((k<<1)+1, mid+1, r);
  8. sum[k] = ((ll)sum[k<<1] + sum[(k<<1)+1]) % MOD;
  9. }
  10. void add(int k, int l, int r, int v) {
  11. lazy[k] = ((ll)lazy[k] + v) % MOD;
  12. sum[k] = (sum[k] + (ll)(r-l+1) * v) % MOD;
  13. }
  14. void mul(int k, int l, int r, int v) {
  15. lazy[k] = ((ll)lazy[k] * v) % MOD;
  16. lazy2[k] = ((ll)lazy2[k] * v) % MOD;
  17. sum[k] = ((ll)sum[k] * v) % MOD;
  18. }
  19. void pushdown(int k, int l, int r, int mid) {
  20. if (lazy2[k]!=1) {
  21. mul(k<<1, l, mid, lazy2[k]);
  22. mul((k<<1)+1, mid+1, r, lazy2[k]);
  23. lazy2[k] = 1;
  24. }
  25. if (lazy[k]) {
  26. add(k<<1, l, mid, lazy[k]);
  27. add((k<<1)+1, mid+1, r, lazy[k]);
  28. lazy[k] = 0;
  29. }
  30. }
  31. void modify(int k, int l, int r, int x, int y, int v) {
  32. if (l>=x && r<=y) {add(k, l, r, v); return;}
  33. int mid = l+r >> 1;
  34. pushdown(k, l, r, mid);
  35. if (x<=mid) modify(k<<1, l, mid, x, y, v);
  36. if (y>mid) modify((k<<1)+1, mid+1, r, x, y, v);
  37. sum[k] = ((ll)sum[k<<1] + sum[(k<<1)+1]) % MOD;
  38. }
  39. void modify2(int k, int l, int r, int x, int y, int v) {
  40. if (l>=x && r<=y) {mul(k, l, r, v); return;}
  41. int mid = l+r >> 1;
  42. pushdown(k, l, r, mid);
  43. if (x<=mid) modify2(k<<1, l, mid, x, y, v);
  44. if (y>mid) modify2((k<<1)+1, mid+1, r, x, y, v);
  45. sum[k] = ((ll)sum[k<<1] + sum[(k<<1)+1]) % MOD;
  46. }
  47. int query(int k, int l, int r, int x, int y) {
  48. if (l>=x && r<=y) return sum[k];
  49. int mid = l+r >> 1, res = 0;
  50. pushdown(k, l, r, mid);
  51. if (x<=mid) res = ((ll)res + query(k<<1, l, mid, x, y)) % MOD;
  52. if (y>mid) res = ((ll)res + query((k<<1)+1, mid+1, r, x, y)) % MOD;
  53. return res;
  54. }

标记永久化

对于树套树,主席树等使用到线段树的比较复杂的数据结构,打标记后 pushdown、pushup 是很费劲的。

思路:不下传标记;在路过该节点的时候把修改对答案的影响加上,来省去标记下放的过程。

zkw Segment Tree

  1. int zkw; ll t[N<<2], laz[N<<2];
  2. inline void update(int x, int y, ll val) {
  3. ll l=0, r=0, f=1;
  4. for (x+=zkw-1, y+=zkw+1; x^y^1; x>>=1, y>>=1, f<<=1) {
  5. t[x]+=val*l, t[y]+=val*r;
  6. if (~x&1) laz[x^1]+=val, t[x^1]+=val*f, l+=f;
  7. if (y&1) laz[y^1]+=val, t[y^1]+=val*f, r+=f;
  8. }
  9. for (; x; x>>=1, y>>=1) t[x]+=val*l, t[y]+=val*r;
  10. }
  11. inline ll query(int x, int y) {
  12. ll res=0, l=0, r=0, f=1;
  13. for (x+=zkw-1, y+=zkw+1; x^y^1; x>>=1, y>>=1, f<<=1) {
  14. if (laz[x]) res+=laz[x]*l;
  15. if (laz[y]) res+=laz[y]*r;
  16. if (~x&1) res+=t[x^1], l+=f;
  17. if (y&1) res+=t[y^1], r+=f;
  18. }
  19. for (; x; x>>=1, y>>=1) res+=laz[x]*l, res+=laz[y]*r;
  20. return res;
  21. }
  22. for (zkw=1; zkw<=n+1; zkw<<=1);
  23. for (int i=zkw+1; i<=zkw+n; i++) scanf("%lld", t+i);
  24. for (int i=zkw-1; i>0; --i) t[i]=t[i<<1]+t[i<<1|1];

NOIp 数据结构专题总结 (2):分块、树状数组、线段树的更多相关文章

  1. 洛谷P2414 阿狸的打字机 [NOI2011] AC自动机+树状数组/线段树

    正解:AC自动机+树状数组/线段树 解题报告: 传送门! 这道题,首先想到暴力思路还是不难的,首先看到y有那么多个,菜鸡如我还不怎么会可持久化之类的,那就直接排个序什么的然后按顺序做就好,这样听说有7 ...

  2. 树状数组 && 线段树应用 -- 求逆序数

    参考:算法学习(二)——树状数组求逆序数 .线段树或树状数组求逆序数(附例题) 应用树状数组 || 线段树求逆序数是一种很巧妙的技巧,这个技巧的关键在于如何把原来单纯的求区间和操作转换为 求小于等于a ...

  3. hdu1394(枚举/树状数组/线段树单点更新&区间求和)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意:给出一个循环数组,求其逆序对最少为多少: 思路:对于逆序对: 交换两个相邻数,逆序数 +1 ...

  4. hdu 1166:敌兵布阵(树状数组 / 线段树,入门练习题)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  5. hdu 5147 Sequence II【树状数组/线段树】

    Sequence IITime Limit: 5000/2500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem ...

  6. 【洛谷4396/BZOJ3236】[AHOI2013]作业(莫队+分块/树状数组/线段树)

    题目: 洛谷4396 BZOJ3236(权限) 这题似乎BZOJ上数据强一些? 分析: 这题真的是--一言难尽 发现题面里没说权值的范围,怕出锅就写了离散化.后来经过面向数据编程(以及膜神犇代码)知道 ...

  7. 数据结构--树状数组&&线段树--基本操作

    随笔目的:方便以后对树状数组(BIT)以及基本线段树的回顾 例题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 例题:hdu 1166 敌兵布阵 T ...

  8. [SDOI2009]HH的项链-树状数组/线段树

    树状数组: #include<bits/stdc++.h> using namespace std; ; int id[maxn],tree[maxn],vis[maxn],num[max ...

  9. 「CodePlus 2017 11 月赛」Yazid 的新生舞会(树状数组/线段树)

    学习了新姿势..(一直看不懂大爷的代码卡了好久T T 首先数字范围那么小可以考虑枚举众数来计算答案,设当前枚举到$x$,$s_i$为前$i$个数中$x$的出现次数,则满足$2*s_r-r > 2 ...

  10. 【bzoj2819】Nim(dfs序+树状数组/线段树)

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=2819 首先根据SG定理,可得若每堆石子数量的异或值为0,则后手必胜,反之先手必胜.于是 ...

随机推荐

  1. composer的自动加载机制(autoload)

    composer的出现真是让人们眼前一亮,web开发从此变成了一件很『好玩』的事情,开发一个CMS就像在搭积木,从packagist中取出『积木』搭建在自己的代码中,一点一点搭建出一个属于自己的王国. ...

  2. IDEA activate-power-mode插件

    一 下载activate-power-mode插件 方法1:插件库下载: 地址:http://plugins.jetbrains.com/plugin/8330-activate-power-mode ...

  3. 第一次工作->笔记:在phpstrom2019上搭建phpunit单元测试环境,php环境使用docker

    前言:公司大佬让我开发一个工具,并合并到他的工具包中,使用的是github 说明:这里的php环境使用的是laradock.感兴趣的道友自行查找. 工具:php.phpstrom.phpunit.do ...

  4. Chrome打开标签页预览

    类似于Microsoft Edge浏览器上的标签页缩略图预览非常方便,其实现在谷歌浏览器正在测试相关的功能,如果想提前体验,就在地址栏输入"chrome://flags"并按下回车 ...

  5. [Python3 填坑] 015 __str__ 与 __repr__ 的区别

    目录 1. print( 坑的信息 ) 2. 开始填坑 2.1 上例子 2.2 关系与区别 Python 3.7.3 的官方文档 网上看到一个例子,运行了一下 简单地说 1. print( 坑的信息 ...

  6. 批量调整word 图片大小

    打开文档后,按Alt+F11,在左边Porject下找到ThisDocument,右键插入模块,贴上下面的 Sub Macro()For Each iShape In ActiveDocument.I ...

  7. Javascript 数组的一些操作

    (1) shift  删除原数组第一项,并返回删除元素的值:如果数组为空则返回undefined var a = [1,2,3,4,5]; var b = a.shift(); //a:[2,3,4, ...

  8. combox系列问题集

    visual studio崩溃 你是不是经常会遇到一编辑combox,visual studio就会立马崩溃.一直都无法理解是什么原因,然后后来发现居然是因为有道的截屏翻译,关掉截屏翻译就好了. co ...

  9. linux单机部署kafka(filebeat+elk组合)

    filebeat+elk组合之kafka单机部署 准备: kafka下载链接地址:http://kafka.apache.org/downloads.html 在这里下载kafka_2.12-2.10 ...

  10. 联想笔记本 thinkpad BIOS 超级密码 Supervisor Password 清除 破解 亲测有效 转载地址https://blog.csdn.net/ot512csdn/article/details/72571674

    联想笔记本 thinkpad BIOS 超级密码 Supervisor Password 清除 破解 亲测有效 转载地址https://blog.csdn.net/ot512csdn/article/ ...