系列索引:

  • NOIp 数据结构专题总结 (1)
  • NOIp 数据结构专题总结 (2)

STL structure

std::vector

#include <vector>
std::vector<type> v;
v.push_back(x);
v.pop_back();
int *a = new int[N];

std::bitset

#include <bitset>
std::bitset<size> bs;

神似 bool 数组。

SAO操作:

std::bitset<N> g[N]; // store a graph, O(n^2/32)

std::map

#include <map>
std::map<typeA, typeB> mp;
mp[x] = y;map<int,bool> g[n];
g[x][y] = true;
map<int,bool>::iterator it;
for (it=g[x].begin(); it!=g[x].end(); ++it)it->first, it->second

std::queue

#include <queue>
std::queue<type> q;
q.push(x);
q.pop();
x = q.front();

std::stack

#include <stack>
std::stack<type> s;
s.push(x);
s.pop();
x = s.top();

std::deque

#include <queue> / #include <deque>
std::deque<type> dq;

std::priority_queue

#include <queue>
std::priority_queue<type> pq; // default: greater first
std::priority_queue<int, std::vector<int>, std::greater<int> > pq; // lower first
struct type { friend bool operator < (type a, type b) {return ...;} };
struct cmp { bool operator() (type a, type b) {return ...;} };
std::priority_queue<type, std::vector<type>, cmp> pq;

std::set

#include <set>
std::set<type> st;          // 会自动去重
std::multiset<type> st2;    // 不去重

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

堆 Heap

Pure

复杂度均摊 \(O(\log{n})\).

void put(int x) {int now = ++heap_size, next;heap[heap_size] = x;while (now > 1) {next = now >> 1;if (heap[now] >= heap[next]) break; // lower rootswap(heap[now], heap[next]);now = next;}
}int get(int x) {int now = 1, next, res = heap[1];heap[1] = heap[heap_size--];while ((now << 1) <= heap_size) {next = now << 1;if (next < heap_size && heap[next+1] < heap[next]) next++;swap(heap[now], heap[next]);}return res;
}

堆的初始化:新建一个空堆,把这些元素依次加进堆,时间 \(O(n\log{n})\)。如果把这些元素 random_shuffle 一下再加进来,期望时间 \(O(n)\)。可以先随意把这些元素放进完全二叉树,再考虑从底向上令每个子树满足堆性质。

堆的删除:因为我们只关心堆顶的元素,我们可以把被删掉的元素暂时留在堆中,并保证当前堆顶的元素未被删除即可。一种实现方法是再开一个堆存储被删除但留在原堆中的元素,一旦两个堆堆顶相等,就一起弹出堆顶。总时间复杂度 \(?(?\log{?})\),这个方法也适用于 std::priority_queue

STL <algorithm>

void put(int x) {heap[++heap_size] = x;// greater heappush_heap(heap + 1, heap + heap_size + 1);// lower heappush_heap(heap + 1, heap + heap_size + 1, greater<int>());
}int get() {// greater heappop_heap(heap + 1, heap + heap_size + 1);// lower heappop_heap(heap + 1, heap + heap_size + 1, greater<int>());return heap[heap_size--];
}

STL std::priority_queue

(refer to above)

并查集 Disjoint Set

路径压缩优化:查询一个元素时,将其到根路径上所有元素的父亲更新为当前的根。时间复杂度 \(\approx O(n)\)(均摊每次 \(O(1)\))。只用路径压缩优化的并查集实际上能被构造数据卡到 \(O(n\log{n})\)。

for (int i=1; i<=n; i++) fa[i]=i;int find(int x) {return fa[x]==x ? x : fa[x]=find(fa[x]); }
void join(int x, int y) {x=find(x),y=find(y); fa[x]=y; }

带权并查集:在集合的根上加一个值为 \(x\) 的标记。对于一般的带权并查集,一个元素到根路径上的标记之和就是这个元素的实际权值。路径压缩时需要注意路径压缩对标记效果的影响。

int f[], sum[];int fa(int x) {if (f[x]==x) return x;else {int r=fa(f[x]);sum[x]+=sum[f[x]];return f[x]=r;}
}int main() {int n, m;while (~scanf("%d%d", &n, &m)) {for (int i=0; i<=n; ++i) fa[i]=i;for (int i=1, x, y, z; i<=m; ++i) {scanf("%d%d%d", &x, &y, &z);int fx=fa(x), fy=fa(y);if (fx!=fy) f[fy]=fx, sum[fy]=sum[x]-sum[y]+z; // 类似向量运算else if (sum[y]-sum[x]!=z) ++ans; // 发现矛盾}printf("%d\n", ans);}return 0;
}

带权并查集可参考 Link

按秩合并优化:“秩”即并查集维护的有根树的深度。合并两个集合时,可以选择深度较小的有根树连接到另一棵上,深度较大的有根树深度会发生改变仅当两树深度相等。如果我们定义一个点的树深度为 \(0\),在这种合并策略下,深度为 \(i\) 的有根树至少有 \(2^i\) 个元素,那么每次操作的时间复杂度显然不超过 \(O(\log{n})\),总时间复杂度 \(O(n\log{n})\)。显然可以在按秩合并的同时采用路径压缩进一步优化,时间复杂度 \(O(n\cdot\alpha(n))\)。

for (int i=1; i<=n; i++) fa[i]=i;int find(int x) {return fa[x]==x ? x : fa[x]=find(fa[x]); } //有路径压缩void join(int x, int y) {x=find(x),y=find(y);if (rank[x] < rank[y]) fa[x]=y;else {fa[y]=x; if(rank[x]==rank[y]) ++rank[x]; }
}

操作撤消:未使用任何优化时,直接将合并操作时连接的边删去即可。使用路径压缩优化后,一次合并操作连接的边可能被压缩掉,难以撤销;如果只使用按秩合并优化,显然不会影响撤销操作。支持撤销操作的并查集可以做到 \(O(n\log{n})\) 的总时间复杂度。

按大小合并优化:每次将较小的集合的根连接到较大的上。考虑一个元素到根的路径上,每经过一条边,说明其所在集合的大小至少扩大一倍,显然不超过 \(O(\log{n})\) 条。时间复杂度 \(O(n\log{n})\)。

ST 表 Sparse Table

Range Maximum/Minimum Query:用 \(f(k,i)\) 表示 \([i,i+2^k-1]\) 的最大值,则有 \(f(k+1,i)=\max\{f(k,i),f(k,i+2^k)\}\)(最小值同理)。查询 \([l,r]\) 时,我们找到最小的 \(k\) 满足 \(2^{k+1}\ge r-l+1\),由于重复统计不影响最值,\(\max⁡[l,r]=\max\{f(k,l),f(k,r-2^k+1)\}\)。预处理 \(O(n\log{n})\),每次查询 \(O(1)\)。

inline void ST() {for (int i=1; i<=n; i++) f[i][0]=data[i];for (int j=1; (1<<j)<=n; ++j)for (int i=1; i+(1<<j)-1<=n; ++i)f[i][j] = max(f[i][j-1], f[i+(1<<j-1)][j-1]);
}inline int query(int l, int r) {int k=0;for (; (1<<k)<=(r-l+1); ++k); --k;return max(f[l][k], f[r-(1<<k)+1][k]);
}

求 LCA:ST 表 + DFS 序。 (refer to Graph Theory)

Hash 表

将复杂信息按其 Hash 值存储到对应位置上。数组 + 链表。每次期望时间 \(O(1)\)。

自然溢出:高效,省去取模。

保证正确性

  • 模数尽量采用质数,避免被数论相关性质影响。
  • 双 Hash:用两种不同的方式求出 Hash 值分别对比。
  • 混合 Hash:乘法、加法、异或、取模。
  • 随机 Hash 中用到的常数,例如模数、乘数等,避免针对。

杂项

Huffman 树和 Huffman 编码:参考 Link

转载于:https://www.cnblogs.com/greyqz/p/ds.html

NOIp 数据结构专题总结 (1):STL、堆、并查集、ST表、Hash表相关推荐

  1. 数据结构(二)——Trie、并查集、堆

    前言 重学算法第5天,希望能坚持打卡不间断,从基础课开始直到学完提高课. 预计时长三个月内,明天再来!肝就完了 2月17日,day05 打卡 今日已学完y总的 算法基础课-2.3-第二章 数据结构(二 ...

  2. 【数据结构与算法】森林版并查集V1.0的Java实现

    并查集 并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中.这一类问题近几年 ...

  3. 数据结构 单词查找 二分法-索引表-Hash表

    问题说明: 从标准输入中读入一个英文单词及查找方式,在一个给定的英文常用单词字典文件dictionary3000.txt中查找该单词,返回查找结果(查找到返回1,否则返回0)和查找过程中单词的比较次数 ...

  4. [数据结构、读书笔记、C++] 并查集详解

    介绍 并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的 合并及查询 问题. 其主要操作为: Union(合并) :将两个节点所在集合合并为一个集合 Find (查询) ...

  5. hdu6557 Justice(小根堆+并查集)

    题意: 有n个砝码,每个砝码有一个权值k(i),表示重量为1/2k(i), 判断是否有可能将砝码分为两组,满足每组的重量都>=1/2 如果有解则输出方案 数据范围:n<=1e5,1< ...

  6. BZOJ 1455: 罗马游戏( 配对堆 + 并查集 )

    可并堆水题 --------------------------------------------------------- #include<bits/stdc++.h> using ...

  7. 数据结构之树的应用:并查集

    树的应用:并查集 并查集的概念: 三种基本操作: 例: 代码实现: 并查集的概念: 将所有的数据元素放在一个集合中,将集合分成若干个互不相交的子集,每一个子集对应一颗树,所有的自己组成森林. 三种基本 ...

  8. 【数据结构和算法笔记】用并查集求解等价关系

      模板: class UF { private:vector<int>father;//father数组vector<int>rank;//秩int count;//连通分支 ...

  9. 【bzoj 入门OJ】[NOIP 热身赛]Problem C: 星球联盟(并查集)

    Problem C: 星球联盟 Time Limit: 4 Sec  Memory Limit: 256 MB Submit: 57  Solved: 15 [Submit][Status][Web ...

最新文章

  1. Android Gradle Plugin 源码解析(上)
  2. Redis在Linux系统的配置优化
  3. power shell远程_PowerShell入门教程之远程操作运行PowerShell的方法
  4. 异常与锁的释放(synchronized )
  5. Redux Vuex
  6. 【QGIS入门实战精品教程】4.5:QGIS打开Excel中的点坐标,并生成矢量文件
  7. HttpSession 和 HttpSession
  8. MyEclipse断点调试不可用解决办法
  9. mysql存储过程实va_MySQL存储过程学习 (1)
  10. JavaWeb——IOC
  11. Django中ORM常用字段及字段参数
  12. 保密协议无效认定_保密协议其实并没用?
  13. 计算机网络实验(二)2交换机的基本配置与管理
  14. Android端的新浪微博论文,android新浪微博客户端开发毕业论文.doc
  15. 敏捷其实很简单(7) Scrum Master的7种武器之长生剑和孔雀翎
  16. win7+nfs文件服务器,win7 nfs服务器设置
  17. Web实时语音/视频聊天/文件传输
  18. 魔方世界连服务器未响应,为什么魔方世界显示无法连接服务器 | 手游网游页游攻略大全...
  19. 初学Android,图形图像之使用Canvas,Paint绘图(二十五)
  20. android 滑动标签框架,Android实现网易严选标签栏滑动效果

热门文章

  1. boost::coroutine模块实现非对称协程的测试程序
  2. GDCM:gdcm::Printer的测试程序
  3. 宏BOOST_TEST_ALL_WITH的用法实例
  4. boost::container模块实现分配器参数的测试程序
  5. Boost:基于Boost的阻塞udp回显服务器
  6. ITK:向二进制图像添加噪声
  7. VTK:结构化网格之BlankPoint
  8. 使用Qt D-Bus适配器
  9. Qt Creator桌面平台
  10. C++longest common subsequence最长公共子序列的实现(附完整源码)