//https://img2018.cnblogs.com/blog/1646268/201908/1646268-20190806114008215-138720377.jpg

qbxt学习笔记

10.1

写的时候是10.3了,因为前面没有这么充足的时间整理,所以根据课件来整理一下

搜索

10.2

写的时候是10.3了,因为前面没有这么充足的时间整理,所以根据课件来整理一下

贪心

思想

贪心是一种解题策略,更多是一种解题思想
使用贪心方法需要注意局部最优与全局最优的关系(用于区分贪心和动态规划),选择当前状态的局部最优并不一定能推导出问题的全局最优
利用贪心策略解题,需要解决两个问题:
该题是否适合于用贪心策略求解。
如何选择贪心标准,以得到问题的最优解 。
常见思路是

  1. 后悔贪心,按照贪心策略处理,拿到某一个时,如果无法再拿,去掉以往的某个最不行的,使问题更优
  2. 排序后思考。问题与顺序无关时,有序比混序更容易求解

可以用贪心解决的题目特点

可以通过局部的贪心选择来达到问题的全局最优解,运用贪心策略解题,一般来说需要一步步的进行多次的贪心选择。在经过一次贪心选择后,原问题将变成一个相似的,但规模更小的问题,之后的每一步都是当前看似最佳的选择,且每一个选择都仅做一次。
原问题的最优解包含子问题的最优解,即具有最优子结构的性质,但并不是所有具有最优子结构的问题都可以用贪心策略求解。

分治

分治分治,分而治之,分治算法就是将一个大问题划分为几个更小规模的形式相同的子问题并加以解决,通过解决子问题最后解决总问题。
分治算法在OI中的运用主要在两个方面
1.二分查找、三分查找、二分答案
2.直接考察分治
有几个比较广泛的应用比如归并排序,快速幂

二分查找

基本想法:如果序列是有序的,就可以在log(n)的时间内查找一个数
序列有序,需要多次查找
注意:如果问题没有思路,同时问题的答案与数据位置无关,可以先排序在思考,这是一个小技巧

二分答案

常见于最小值最大或者最大值最小问题(基本上可以把这看做二分答案的标志)
要求:
1:如果答案确定,我们能够快速判断答案是否合法
2:答案具有可二分性,即如果答案为i是可行的,答案为i+1即可行
牺牲log(n)的复杂度,把求最优化问题变成了一个判断是否可行的问题,有时候能够简化问题

三分(一般用不到)

三分的难度要略低于二分(因为扩展出来的形式少)
三分的用处在于求一个单峰函数的最值
单峰函数,例如:
image
实现
image

10.3

线段树

  1. 维护什么东西;
  2. 怎么维护标记;
  3. 左右儿子怎么合并;
  4. 标记怎么影响维护的东西;

线段树题目

1.区间求和;
2.区间加一段斐波那契数列的值;
假设第一项是 \(a\),第二项是\(b\)\(x\times a+y\times b\)
\(f[1][0]=1;f[1][1]=0;//f[1]=1\times a+0\times b\);
\(f[2][0]=1;f[2][1]=0;//f[2]=0\times a+1\times b\);
\(f[i][0]\times a+f[i][1]\times b\)表示斐波那契数列第i项的值
\(tag\)一个是\(ab\),一个是\(bb\),表示上面的\(a,b\)

区间加等差数列,求区间最大值;

\(n\) 个数,求 \(l\text{~}r\) 的区间内选 \(k\) 个数相乘的总方案相加的总和;
\(n\le 5e4,k\le 20\);
\(ans[i]\)\(i\) 个数乘起来的答案

for(int i=0;i<=20;i++)//我要求选i个数的答案
  for(int j=0;j<=i;j++)//从左儿子里面选j个数
     ans.ans[i]+=l.ans[j]*r.ans[i-j];
return ans;

给你 \(n\) 个数,询问 \(l\text{~}r\) 这个区间内有多少个数比前面的都大,支持单点修改;
\(n\le 5e4\);
\(ans\) 当前区间内有多少点是大于前面的数的
\(maxv\) 当前区间内最大的值

query(int l,int r,int rt,int v)

当前的线段树节点是 \(l\)\(r\)\(rt\);
在这段区间前面放了一个 \(v\) 之后的比前面的数都大的数量

维护两个东西:区间和和最大值

如果最大值是1就直接退出

不等于1就直接递归求解(一个数最多暴力开根10次就可以变成1)

动态规划基础

状态与状态图

转移方式:前向转移和后向转移
编写方式:\(for\) 循环(广度优先搜索),\(dfs\)(深度优先搜索)
优化角度:时间复杂度=状态复杂度 \(\times\) 转移复杂度

基本原理

  1. 最优性原理:作为整个过程的最优策略,它满足:相对前面决策所形成的状态而言,余下的子策略必然构成“最优子策略”。
  2. 无后效性原则:给定某一阶段的状态,则在这一阶段以后过程的发展不受这阶段以前各段状态的影响,所有各阶段都确定时,整个 过程也就确定了。这个性质意味着过程的历史只能通过当前的状态去影响它的未来的发展,这个性质称为无后效性。

常用优化方式

数据结构优化,单调队列优化,前缀和优化,滚动数组,斜率优化
不会

转入转出优缺点:

  1. 转出
    优点:顺向思维,思考难度低。一般采用记忆化搜索编写,类似于写搜索,不易错。适合树、图等不规则转移图
    缺点:转出的状态是未知的,也就意味着转移的负责度难以优化
  2. 转入
    优点:一般for循环编写,代码简洁。转移图有规律,可以通过前缀和、线段树等多种方法优化转移。适合序列等规则转移图
    缺点:需要注意边界等特殊位置,容易出错

状态设计的一些技巧

  1. 从搜索角度思考问题:需要知道什么条件才能继续搜下去,如何将他们简化为动态规划的状态
  2. 增加维数:当我们发现一个状态表示的并不能充分地表示出所有的特征或不满足最优子结构时,我们可以通过增加状态的维数来满足要求。
  3. 交换状态与最优值:由于最优值的规模往往没有太多的限制,所以在某些情况下,我们交换最优值与某一位状态记录的内容,而缩小规模。
  4. 对部分问题进行DP:直接对原问题DP求出答案可能比较困难。可以仅有DP求出原问题答案的一部分信息,然后用其他办法或另外的DP求出答案。
  5. 可行转最优:一些可行性DP问题(一些DP设计出来DP值只有\(true\)或者\(false\)),很多时候可以省去状态的一维,转化成最优性DP(就是DP值是存一个数字最大最小值之类),可以优化复杂度。
  6. 合并本质相同的状态:有一些问题,问题会有多个需要在状态中记录的信息,而这些信息本质都是类似的我们可以合并状态,优化复杂度。

记忆化搜索

我们一般写的动态规划是BFS模式的,即一个点从与它相邻的点转移过来
如果用深搜写动态规划,就可以说是记忆化

基本思路:

对于每个状态,存储该状态返回信息
以后再到该状态,直接调用存储信息即可

线性动态规划

最典型的特征就是状态都在一条线上,并且位置固定,问题一般都规定只能从前往后取状态,解决的办法是根据前面的状态特征,选取最优状态作为决策进行转移。
设前\(i\)个点的最优值,研究前\(i-1\)个点与前\(i\)个点的最优值
利用第\(i\)个点决策转移。

区间动态规划

该类问题的基本特征是能将问题分解成为两两合并的形式。解决方法是对整个问题设最优值,枚举合并点,将问题分解成为左右两个部分,最后将左右两个部分的最优值进行合并得到原问题的最优值。有点类似分治的解题思想。
设前\(i\)\(j\)的最优值,枚举剖分(合并)点,将\((i,j)\)分成左右两区间,分别求左右两边最优值。

背包类动态规划

通常采用\(f[i][j]\) 表示前i个物品容量为j的最优价值
根据状态枚举顺序可以变为01背包和多重背包
解题时关注:
问题转化(把题目的额外限制变成容易处理的部分)

树形动态规划

大多数情况是树上套一个背包
优化
合理控制每一个点的枚举大小,即不做过分的计算
也可以变成左儿子右兄弟来处理(但只是从这个角度思考,实际实现最好不要)

期望?

10.4(蚌)

状态压缩动态规划

一般以\(f[i][S]\)为状态,\(S\)为一个二进制数(当然也可以是三进制四进制数,不过这时候建议处理前先把\(S\)拆成数组)
要注意用好位运算,这样可以加速
联赛考的一般比较基础
一般用记忆化搜索实现(便于理解和编写)

常用位运算

  1. !!(s & (1 << i)):判断第 \(i\) 位是否是 \(1\);
  2. s |= 1<<i:把第 \(i\) 位设置成 \(1\)
  3. s &= ~(1<<i) :把第 \(i\) 位设置成 \(0\)
  4. s ^= 1<<i:把第 \(i\) 位的值取反
  5. s & = s - 1:把一个数字 \(s\) 二进制下最靠右的第一个 \(1\) 去掉
  6. for (s0 = s; s0; s0 = (s0 - 1) & s); :依次枚举 \(s\) 的子集
    (本来想用\(latex\)渲染一下但好像有问题)

数位动态规划

OI中经常需要统计区间\([l,r]\)的满足题意的数的个数,这往往可以转换成求\([0,r]-[0,l)\)
对于求区间\([0,n)\)有一个通用的方法。
对于一个小于\(n\)的数,肯定是从高位到低位出现某一位\(<n\)的那一位。
\(n = 58\) \(n\)为十进制数。
\(x = 49\) 此时\(x\)的十位\(<n\)
\(x = 51\) 此时\(x\)的个位\(<n\)
有了上述性质,我们就可以从高到低枚举第一次\(<n\)对应位是哪一位。
这样之前的位确定了,之后的位就不受\(n\)的限制即从\(00...0\)~\(99...9\),可以先预处理,然后这时就可以直接统计答案。
预处理\(f\)数组。
\(F[i,st]\) 代表 位数为\(i\)(可能允许前导\(0\)。如\(00058\)也是个\(5\)位数),状态为\(st\)的方案数。这里\(st\)根据题目需要确定。
\(i=4,f[i,st]\)也就是\(0000\)~\(9999\)的符合条件的数的个数(十进制)
决策第\(i\)位是多少\((such as 0\)~\(9)\)
\(F[i,st] = F[i,st] + f[i–1,st']\)
\(st'\)为相对应的状态
从高位到低位处理!!

这一天基本没听懂啊草。
明天不知道会讲些什么奇怪的东西。

10.5

图的定义:图\(G\)是一个有序二元组\((V,E)\),其中\(V\)称为点集\((Vertices Set)\)\(E\)称为边集
有向图、无向图:如果给图的每条边规定一个方向,那么得到的图称为有向图。在有向图中,与一个节点相关联的边有出边和入边之分。相反,边没有方向的图称为无向图。

  • \((Degree)\):一个顶点的度是指与该顶点相关联的边的条数,顶点\(v\)的度记作\(d(v)\)
  • 入度\((In-degree)\)和出度\((Out-degree)\):对于有向图来说,一个顶点的度可细分为入度和出度。一个顶点的入度是指与其关联的各边之中,以其为终点的边数;出度则是相对的概念,指以该顶点为起点的边数。
  • 自环\((Loop)\):若一条边的两个顶点为同一顶点,则此边称作自环。
  • 路径\((Path)\):就是链接两个点的边形成的路

特殊的图

  • 没有环的无向图:树
  • 有向图的树:外向树、内向树
  • 树的扩展:
  • 仙人掌图:边仙人掌、点仙人掌
  • \(DAG(Directed\) \(Acyclic\) \(Graph)\):有向无环图
  • 二分图

图的存储

  • 邻接链表(链式前向星)
  • 邻接矩阵

最短路问题

多源最短路

这个应该不用多说,主要是用的\(Floyd\)(你也可以叫他TLE大法)
这个算法啥都行,什么负边,自环,负环都能处理,但他复杂度是 \(O(n^{3})\)
所以一般用不到,除非题目数据很小

单源最短路

这个算法就比较多了

Dijkstra

这个不多说,我写过博客》Dijkstra及其堆优化

Bellman-Ford

这个也不多说,节约一下本来就不多的空间放个详细的博客Bellman-Ford算法详解

SPFA(某已死算法)

就是上面那个算法的一个队列优化,同样:SPFA

差分约束

之前写的博客,我太菜了实际不会用,看看就好差分约束学习笔记

生成树

最小生成树

这个很简单,有两种算法一个是 kruscal,一个是prim(基本不用,可以不学)
博客:最小生成树Prim算法和Kruskal算法

次小生成树

先建一颗最小生成树,然后枚举每一个非树边,然后找到当前边加入后组成的环,然后把里面最大的替换成当前枚举到的非树边。

10.6

二分图

长度为奇数的环会导致不是二分图。
当然这个我也写过博客,当时是为了给同学分享。
二分图学习笔记

网络流

这个算法学长曾给我们讲过,但是因为过于,emmm算了放个链接以后来填上(这才DAY 5就已经开始卡了,我考虑一下要不要只留知识点)网络流学习笔记

今天的东西有点多直接打个压缩包吧
https://files-cdn.cnblogs.com/files/blogs/765985/day6-2.zip?t=1665062251

posted @ 2022-10-03 11:48  北烛青澜  阅读(66)  评论(0编辑  收藏  举报