当前位置: 首页 > news >正文

题解:P13976 数列分块入门 1(分块入门)

树状数组板子题。

好吧开玩笑的,这题是分块入门,我们用分块做。


什么是分块?

分块是一种思想,但不是一种算法。算法是基于方法的,方法又是基于思想的。

正如其名,分块就是把数列分成若干个块,然后计算答案。如何计算?如果区间问题的区间在块内则使用一种方法计算,如果不在一个块之内(块间)则使用另一种方法。通常来讲,这个另一种方法是处理最左边的块的一部分、最右边的块的一部分和中间的块。

我们来看这题。

::anti-ai[但我还是想写树状数组啊啊啊啊啊啊!!]

首先看区间加法。考虑块内如何处理。可能不是很好处理,因为是一个规模变为块长 LLL,但是和原问题一模一样的问题。可以考虑暴力修改。

使用类似的方法处理掉块间的左右两边的不完整的块,对于中间的块,直接处理太笨了,可以打标记。

标记不必在某个时刻下传到一个块内的所有数字,可以永久化。修改的时候当它不存在,而查询的时候加上查询的数字所在的块的大小即可。

查询时间复杂度是 Θ(1)\Theta(1)Θ(1),块内修改是 O(L)\mathcal O(L)O(L),块间修改是 O(L+nL)\mathcal O\left(L+\dfrac{n}{L}\right)O(L+Ln),最多是 O(L+nL)\mathcal O\left(L+\dfrac{n}{L}\right)O(L+Ln)。这个东西的最小值显然是 L=nL=\sqrt{n}L=n 时的 O(n)\mathcal O(\sqrt{n})O(n)。如果 nnn 不是完全平方数也可以取 ⌊n⌋\left\lfloor\sqrt{n}\right\rfloorn⌈n⌉\left\lceil\sqrt{n}\right\rceiln,对时间复杂度没有影响。通常取向下取整,因为比较简单。

总时间复杂度是 O(nn)\mathcal O(n\sqrt{n})O(nn) 的。记得开 long long

另一件事情是,尽管保证了 aia_iailong long 范围内,直接写代码仍然可能出现 ub。初始 ai=−263a_i=-2^{63}ai=263,然后对整块加上 263−12^{63}-12631,然后对块内的一个 aia_iai 单独加上 −1-11,此时实际的值是 −2-22,存储的标记是 263−12^{63}-12631,存储的 aia_iai−263−1-2^{63}-12631,溢出了,但是通常不会影响结果。要解决这个问题,我们可以假装值对 2642^{64}264 取模,然后输出的时候如果大于等于 2632^{63}263 就转换回去。通常来讲,不做这样的处理也不会影响结果,故我们在 OI 中通常不会对于这样“不会影响结果的溢出”做特殊处理,毕竟看的是输出结果对不对,对了但是有 ub 也是算对的。下面的代码中没有进行处理。

代码:

#include <cstdio>
#include <cmath>using namespace std;long long a[300005], tag[550];int main()
{int n;scanf("%d", &n);for (int i = 1; i <= n; i++){scanf("%lld", a + i);}int blksz = sqrt(n); // blksz = BLocKSiZe = Block Size = 块长for (int i = 1; i <= n; i++){int opt, l, r;long long c;scanf("%d%d%d%lld", &opt, &l, &r, &c);if (opt == 1) printf("%lld\n", a[r] + tag[(r + blksz - 1) / blksz]);else{// 处理修改int lid = (l + blksz - 1) / blksz;int rid = (r + blksz - 1) / blksz;if (lid == rid) // 块内暴力修改{for (int j = l; j <= r; j++){a[j] += c;}}else // 块间修改{// 左右两边暴力修改for (int j = l; j <= lid * blksz; j++){a[j] += c;}for (int j = (rid - 1) * blksz + 1; j <= r; j++){a[j] += c;}// 中间暴力打标记for (int j = lid + 1; j < rid; j++){tag[j] += c;}}}}return 0;
}
// 总结:分块是暴力。

record。

彩蛋:既然没法很好处理块内数据,为什么我们不考虑……对每个块再次分块,然后再次分块,以此类推,直到块长变为 111 呢?实际上这样是可以的,你会发现这成为了一个树的形状。这个东西稍加优化并作用在值域上可以变成 van Emde Boas 树,做到 O(log⁡log⁡V)\mathcal O(\log \log V)O(loglogV) 的很多操作(插入删除查找前驱后继),还能支持卫星数据。我并不会这玩意儿,OI 中也不考。

http://www.dtcms.com/a/550065.html

相关文章:

  • 《XQuery 参考手册》
  • C++ 双指针:从原理到实战的全面解析
  • C++11 std::async()基础用法示例
  • 六安政务中心网站wordpress运行c语言
  • 网站优化哪家专业会展设计师
  • CPU突然飙升,如何定位到问题所在?
  • 查询网站dns服务器郑州网站建设郑州网络推广
  • 专门做中式装修的网站网站的背景图怎么做
  • 谷晟阳风水课程的专业价值与推荐意义
  • ZKAJM-8L1B1 8阵元抗干扰天线技术说明书
  • 网站备案怎么转入牙科医院网站设计怎么做
  • 线性回归(Linear Regression)与 scikit-learn线性回归函数详解
  • 网站开发导向图网页编程html
  • c#+ visionpro汽车行业,机器视觉通用检测程序源码 产品尺寸检测,机械手引导定位等
  • OpenCV调用drawContours后轮廓消失
  • 处理大型excel文件的技术选型
  • [Comake][D1][AI_AO][bf_ssl_demo]
  • 网站建设方案报价一个用vue做的网站
  • 网上书城网站开发的目的与意阜宁城乡建设局网站
  • 数据结构——三十四、Floyd算法(王道408)
  • Linux服务器配置ssh免密登陆
  • JUC(二)-- 并发编程
  • 湖北省住房和城乡建设部网站大连网站建设收费
  • 石家庄网站建设今天改网名做淘宝客没网站
  • DoIP(Diagnostic over IP)路由激活与诊断请求
  • 协议选型框架
  • Double DQN(DDQN)详解与实现
  • 针对Java集合框架的面试题有哪些
  • HashMap 的哈希算法与冲突解决:深入 Rust 的高性能键值存储
  • 甘肃省建设厅官方网站质监局淮安网站优化