【数据结构】二进制分组解决一类强制在线问题

Text

这种技巧来源于论文:许昊然《浅谈数据结构题的几个非经典解法》

你需要对什么东西支持若干个修改和询问操作,强制在线,如果去掉强制在线,那么是可以对时间分治来解决的。

换句话说,这类题目满足能够对于每个修改单独计算对每个询问的答案(修改之间是独立的)
我们将修改操作每2的幂次分一组,每一组用数据结构维护

当出现询问时,就暴力跳每一组,在组中的数据结构查询。
出现新的修改时,就类似2048(逃)一样的向左合并组。

假设当前我们有13个修改操作,组的大小是8 4 1
新加入一个修改,变成8 4 1 1
合并就变成 8 4 2
以此类推。

合并组的时候就暴力重构这个数据结构

分析这样的时间复杂度
论文中如是说

考虑我们加入第k个操作所需要重构的组的大小
可以发现其实就是 l o w b i t ( k ) lowbit(k) lowbit(k)
假设我们维护每一组的数据结构的复杂度为 O ( f ( s i z e ) ) O(f(size)) O(f(size))
组数一定是不超过 log ⁡ k \log k logk组的,那么总的询问时间复杂度就是 O ( q log ⁡ n ∗ f ( n ) ) O(q\log n*f(n)) O(qlognf(n))
总的修改时间复杂度就是 ∑ i = 1 n O ( f ( l o w b i t ( k ) ) ) \sum\limits_{i=1}^{n}O(f(lowbit(k))) i=1nO(f(lowbit(k)))
= ∑ i = 1 log ⁡ n O ( ⌈ n 2 i + 1 ⌉ ∗ f ( 2 i ) ) =\sum\limits_{i=1}^{\log n}O\left(\left\lceil{n\over 2^{i+1}}\right\rceil *f(2^i)\right) =i=1lognO(2i+1nf(2i))
≤ ∑ i = 1 log ⁡ n O ( f ( i ) ) = O ( f ( n ) log ⁡ n ) \leq\sum\limits_{i=1}^{\log n}O(f(i))=O(f(n)\log n) i=1lognO(f(i))=O(f(n)logn)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是示例代码,实现了学生类的定义、二进制文件的写入和读取: ```c++ #include <iostream> #include <fstream> #include <string> using namespace std; class Student { public: string name; string id; string cls; void print() { cout << "Name: " << name << ", ID: " << id << ", Class: " << cls << endl; } }; int main() { int n = 3; // 假设有3个学生 // 创建学生数组 Student students[n]; students[0] = {"Tom", "1001", "Class 1"}; students[1] = {"Jerry", "1002", "Class 2"}; students[2] = {"Mike", "1003", "Class 3"}; // 将学生信息写入二进制文件 ofstream fout("student.dat", ios::binary); fout.write((char*)students, sizeof(Student) * n); fout.close(); // 从二进制文件中读出学生信息并显示 ifstream fin("student.dat", ios::binary); Student s; while (fin.read((char*)&s, sizeof(Student))) { s.print(); } fin.close(); return 0; } ``` 其中,`Student` 类定义了学生的数据结构,包括姓名、学号和班级。`print()` 方法用于将学生信息输出到屏幕上。 在 `main()` 函数中,我们创建了一个包含3个学生的数组,并将它们写入了名为 `student.dat` 的二进制文件中。接着,我们使用 `ifstream` 从二进制文件中逐个读取学生信息,并使用 `print()` 方法将其输出到屏幕上。 需要注意的是,在读写二进制文件时,需要使用 `ios::binary` 模式打开文件,并将结构体或类的指针强制转换为 `char*`,以便进行字节级别的读写。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值