2021-07-07

                                     **关于这几天的复习与学习**

#复习方面
按照学长的要求将一些基础性的知识全部都复习了一遍,也做了一些题,不过基本都是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);//除1号结点外,其他均初始为无穷大
    dist[1]=0;
    for(int i=0;i<n;i++) //n次迭代,每次寻找不在s中距离最近的点t
    {
        int t=-1;// 便于更新第一个点
        for(int j=1;j<=n;j++)
          if(!st[j]&&(t==-1||dist[j]<dist[t])) t=j;
        st[t]=true;  //将t加到s中
        for(int j=1;j<=n;j++)  //用t更新其他点的距离
          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中为什么要存pair呢,首先小根堆是根据距离来排的,所以有一个变量要是距离,其次在从堆中拿出来的时    
    // 候要知道知道这个点是哪个点,不然怎么更新邻接点呢?所以第二个变量要存点。
    heap.push({ 0, 1 }); // 这个顺序不能倒,pair排序时是先根据first,再根据second,这里显然要根据距离排序
    while(heap.size())
    {
        PII k = heap.top(); // 取不在集合S中距离最短的点
        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]; // i只是个下标,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];
}

(看题)添加链接描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值