【分块】LibreOJ 6282 数列分块入门6
题目
题解
数据范围 \(1 \leq n \leq 10^5\),因此进行分块最多分 \(\sqrt{10^5} ≈ 318\) 块。且数据是随机生成的,因此插入数据后,每个块的长度期望值为 \(\frac{318+(318 + 100000/318)}{2} ≈ 475\)。因此,可以使用分块思想解决该问题。
对于每个块,都用一个数组维护,并且维护每个块的元素个数。
对于查询操作,从第一块开始累计元素的个数,易知该步骤的时间复杂度为 \(O(\sqrt{n})\)。当找出 \(a_r\) 所在的块的时候,直接取出该元素即可。
对于插入操作,先查询出要插入的元素是需要插入到第几个块,该步操作时间复杂度 \(O(\sqrt{n})\),随后使用插入排序的思想进行插入,由于每个块的块长期望为 \(\sqrt{n}\) 级别,因此该步操作的时间复杂度也是 \(O(\sqrt{n})\)。
参考代码
#include<bits/stdc++.h> #define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr); using namespace std; typedef long long ll; constexpr int N = 100327; int n, op, l, r, c, len; int a[320][N];//1e5个元素,最多只需要分为317个块 int getPieceSize(int pid) {//获取第pid个块的块长。此处是计算初始块长,添加元素该函数失效 return min(n, pid * len) - (pid - 1) * len; } int main() { IOS cin >> n; len = sqrt(n);//块长,最后一块可能不满len个元素 int num = 1;//块数 for (int i = 1; i <= n; ++ i) { cin >> a[num][i % len]; if (i % len == 0) { a[num][len] = a[num][0]; ++ num; } } //把每个块的元素个数存储在a[i][0] for (int i = 1; i <= num; ++ i) a[i][0] = getPieceSize(i); for (int i = 0; i < n; ++ i) { cin >> op >> l >> r >> c; if (op) {//询问 a[r] 的值 for (int i = 1, j = 0; i <= num; ++ i) { if (j + a[i][0] < r) j += a[i][0]; else { cout << a[i][r - j] << '\n'; break; } } } else {//在第 l 个数字前插入数字 r for (int i = 1, j = 0; i <= num; ++ i) { if (j + a[i][0] < l) j += a[i][0]; else { for (int k = a[i][0]; k >= l - j; -- k) a[i][k + 1] = a[i][k]; a[i][l - j] = r; a[i][0] ++; break; } } } } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 【.NET】调用本地 Deepseek 模型