分块算法(优雅的暴力)
1)分块算法一般将一列数划分为 根号n,同时用一个数组来记录每一个元素的归属块。后续处理都是尽量按照组为单位进行处理,进而节约时间开销。
下面只是展示初始化代码,区间查询和区间修改代码参见洛谷P3372线段树(分块)题目代码
void _init(int n){//先对分块进行初始化操作
int q = sqrt(n);//q个分组
for(int i = 1; i <= q; i++){//确定每一组的起始元素和结尾元素
st[i] = n/q * (i-1) + 1;
ed[i] = n/q * i;
}
ed[q] = n;//将最后一点纳入到最后一块中
//确定每一组的大小
for(int i = 1; i <= q; i++)
size[i] = ed[i] - st[i] + 1;
//确定每个元素的归属组
for(int i = 1; i <= q; i++)
for(int j = st[i]; j <= ed[i]; j++)
bel[j] = i;//第j号元素属于第i组
//保存每一个块的和在数组sum中
for(int i = 1; i <= q; i++)
for(int j = st[i]; j <= ed[i]; j++)
sum[i] += a[j];
}
ST表(稀疏表)
1)ST表(Sparse Table,稀疏表)是一种简单的数据结构,主要用来解决RMQ(Range Maximum/Minimum Query,区间最大/最小值查询)问题。它主要应用倍增的思想,可以实现 [公式] 预处理、 [公式] 查询。
所谓RMQ问题,以最大值为例,是假如有一个数列 [公式] ,给你一个区间 [公式] ,要求 [公式] 。
ST表使用一个二维数组f,对于范围内的所有f[a][b],先算出并存储 [公式] (本文中的区间都是离散意义下的,只包含整数,所以此区间也可以写成[公式] ),这称为预处理。查询时,再利用这些子区间算出待求区间的最大值。
参考博客:https://zhuanlan.zhihu.com/p/105439034
2)代码:
int f[MAXN][21]; // 第二维的大小根据数据范围决定,不小于log(MAXN)
for (int i = 1; i <= n; ++i)
f[i][0] = read(); // 读入数据
for (int i = 1; i <= 20; ++i)
for (int j = 1; j + (1 << i) - 1 <= n; ++j)
f[j][i] = max(f[j][i - 1], f[j + (1 << (i - 1))][i - 1]);
查询时可以利用倍增的思想进行处理,同时记得初始化_log2数组(log2的取下整数),节约算法时间开销。代码如下
//查询[l, r]上的最值
for(int i = 2; i <= n; i++) _log2[i] = _log[i/2] + 1;
int k = _log[r-l+1];//是不是感觉很简单,对!就是这么简单!
int ans = max(f[l][k], f[r-(1<<k)+1][k]);
3)用二维数组以及动态规划的思想,保存数组中的每个独立区间的最大值
链式前向星存储图(树)
1)本质就是用静态数组来模拟表示链表,思想就是邻接表的思想。
关键代码:(视频参考)
变量解释
- to :该条有向边的终点结点值
- w :该有向边的权值
- next:与该有向边同起点的邻接有向边的下标
- tot:Edge内存池中还没被使用的下一个位置指示器(方便后续插入边的操作)
- Head:每个节点的第一个临界点(下面图中的左边第一列)
struct E{
int to, w, next;
}Edge[maxn];
int tot, Head[maxn];
2)插入边——头插法
inline void AddEdge(int u, int v, int w){
//表示需要将一条从u到v的权值为w的有向边插入到Edge数组中
Edge[tot].to = v;
Edge[tot].w = w;
//上面先初始化tot的内存空间,下面两行进行链接处理
Edge[tot].next = Head[u];
Head[u] = tot++;//头插法
}
3)补充:一般情况下还是可以采用邻接表的方式进行存储。在实际实现中一般使用c++中的vector数组进行表示
#include<vector>
using namespace std;
struct E{
int to, w;
}Edge;
vector<Edge> G[maxn];
Z字搜索(特殊性质的矩阵搜索元素)
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
//考虑到矩阵中数字的特殊性,应该是可以想到这样处理的!!!
//Z字查找(扩展思维)
//更优化的,还可以用二分查找。
int m = matrix.size(), n = matrix[0].size();
int x = 0, y = n - 1;
while (x < m && y >= 0) {
if (matrix[x][y] == target) {
return true;
}
if (matrix[x][y] > target) {
--y;
}
else {
++x;
}
}
return false;
}
};
一种非常好用的以空格进行分割字符串的方式
#include<iostream>
#include<sstream>
using namespace std;
int main() {
istringstream str(" this is a text ");
string out;
// 通过使用字符串输出流去滤掉字符串中多余的空格!
while(str >> out) {
cout << out << endl;
}
return 0;
}