**关于这几天的复习与学习**
#复习方面 按照学长的要求将一些基础性的知识全部都复习了一遍,也做了一些题,不过基本都是ACWING上的基础题。 ##前缀和与差分 ###前缀和 前缀和其实就是求一段数组区间内的所有数字之和,只需要当前缀和数组创建出来后,查询一次便只需要O(1)的复杂度,而线性相加则需要O(n)的复杂度,前缀和其实只是一种思想,公式为s[i]=s[i-1]+a[i],(建议数组下标都从1开始) 模板:https://www.acwing.com/problem/content/797/ 二维形式:求前缀和矩阵 1.求s[i,j] 公式:s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]; 2.给定左上角和右下角坐标(x1,y1)、(x2,y2),求其中矩阵的数值的和 公式:s=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]; 模板:https://www.acwing.com/problem/content/798/ ###差分 差分实质上就是前缀和的逆运算。 1.一维形式: 差分数组:b[i]=a[i]-a[i-1]; 查询:b[l]+=c,b[r+1]-=c 模板:添加链接描述 2.二维形式:(二维差分不需要去考虑差分数组的构造) 查询:b[x1][y1]==c;b[x2+1][y1]-=c,b[x1][y2+1]-=c,b[x2+1][y2+1]+=c; 模板:添加链接描述 ##动态规划 ###多重背包问题 01背包问题的变种,不同与01背包中的每样物品只有一件,多重背包每样物品都有有限个数件,第一个办法就是将多重背包拆分成01背包,如:
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
for(int k=0;k<s[i]&&j>=k*v[i];k++)
f[i][j] = max(f[i][j], f[i - 1][j - v[i] * k] + w[i] * k);
这样的复杂度是最高的; 二进制优化: 将物品总共所拥有的s[i]件物品用二进制的方法进行包装,使得从1到s[i]件物品中的任意数量都能从一包装好的物品数量中拼凑出来,可减少计算数量。(看题) 添加链接描述 ###分组背包问题 三重循环枚举,目前没有好办法;(看题) 添加链接描述 ##并查集 并查集说白了就是划分阵营的问题,每个阵营都有一个共同的大哥大,当进行查询操作时便只需要看大哥大是哪一位就可以确定是哪一个阵营,合并也只需要将两个阵营不同的大哥大变成同一个就行。 find()函数(含路径压缩):
int find(int x)
{
int r=x;
while(pre[r]!=r)
r=pre[r];
int i=x,j;
while(i!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
join函数:
void join(int x,int y)
{
int a=find(x);
int b=find(y);
if(a!=b)
{
pre[a]=b;
}
}
看题: 添加链接描述 添加链接描述 添加链接描述 #学习方面 ##最短路 ###朴素Dijkstra 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。 实现:
int Dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[1]=0;
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
if(!st[j]&&(t==-1||dist[j]<dist[t])) t=j;
st[t]=true;
for(int j=1;j<=n;j++)
dist[j]=min(dist[j],dist[t]+g[t][j]);
}
if(dist[n]==0x3f3f3f3f) return -1;
else return dist[n];
}
添加链接描述 ###堆优化Dijkstra 一般来说堆优化就是利用堆优化查询操作,可以用优先队列将将原本需要O(n)复杂度的查询距离最近的点的操作简化为O(1)(存图可以用链式前向星);时间复杂度为O(mlogn);
int dijkstra()
{
memset(dist, 0x3f, sizeof(dist));
dist[0] = 1;
priority_queue<PII, vector<PII>, greater<PII>> heap;
heap.push({ 0, 1 });
while(heap.size())
{
PII k = heap.top();
heap.pop();
int ver = k.second, distance = k.first;
if(st[ver]) continue;
st[ver] = true;
for(int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
if(dist[j] > distance + w[i])
{
dist[j] = distance + w[i];
heap.push({ dist[j], j });
}
}
}
if(dist[n] == 0x3f3f3f3f) return -1;
else return dist[n];
}
(看题)添加链接描述
|