2019.7.29 金华正睿集训总结Day2

3 篇文章 0 订阅
2 篇文章 0 订阅

7.29

上午

分治

普通分治

• 通过将区间分成两个区间,来将问题分成两个子问题

例题:
• 求所有区间的最大值之和

根据分治思想,对于每个区间,都递归分成两部分,边界为1

对于每个区间,先考虑固定左端点 l ,O(n) 求出以 l 为左端点的跨越 mid 的最大值

每次O(n) 求 l ~ mid 的最大值 maxl, 再用 maxr 记录右边第一个比 maxl 大的位置,然后求最大值前缀和 f[i]

则答案为 (maxr - 1 + (mid + 1) + 1) * maxl +f[r] -f[maxr - 1]

再考虑固定右端点同理

• 求所有区间的最大值*最小值之和

四种情况:

1、最值都在左边

枚举 l , 计算有几个 r 满足条件

Ma[l] : 最大的 r 使得 l ~ r 的最大值在 l ~ mid 中

Mi[l]:最大的 r 使得 l ~ r 的最小值在 l ~ mid 中

显然, Ma[i] , Mi[i] 非严格单调

r = {mid + 1, …,min(Ma[l], Mi[l]) }

|r|:r的方案数

所以答案为 |r| * max( l, …, mid) * min( l, …,mid)

2、最大值在左边,最小值在右边

∑ r = M i [ l ] + 1 M a [ l ] \sum_{r = Mi[l] + 1}^{Ma[l]} r=Mi[l]+1Ma[l]max( l,…, mid) * PMi[r]

=max( l,…, mid) * ∑ r = M i [ l ] + 1 M a [ l ] \sum_{r = Mi[l] + 1}^{Ma[l]} r=Mi[l]+1Ma[l] PMi[r]

3、最值都在右边

4.最小值在左边,最大值在右边

剩下两种情况同理

• 求所有区间的 gcd 之和

gcd(L , … , R) = gcd(gcd(L , … , Mid) , gcd(Mid + 1 , … , R))

枚举 L 在左边哪一段, R 在右边哪一段

当 R 固定时,随着 L 的变化暴力分治求gcd

• 求二维平面上最近点对

按 x 排序,从中间切开

先得到左边和右边分别的最近点对距离 d1,d2

得到 d = min(d1,d2

以中间线为一边,在左右两边分别构造宽(x)d,长(y)2d 的矩形,再暴力得到一点在左矩形,一点在右矩形的最近点对

得到最终解

十分神奇的一个结论,中线一侧的矩形中期望有6个点

• 分治多项式乘法

分开乘

例题

旅行者

ZJOI2016

• 给定⼀张 n*m 的带正权网格图,有 Q 组询问,每次询问两对点之间的最短路
• 1<=n*m,Q<=50000

离线操作

把矩形沿较长边切成两半,然后枚举询问

若询问的两点在同侧,则继续递归

否则询问答案必定会被更新

dis[a][b] = min(dis[a][b], dis[a][x] + dis[x][b])

连续区间

• 给定⼀个排列 p[1…n],求有⼏个区间 [L,R] 满⾜ p[L…R]排序后是连续的
• n<=500000

即max(L, … ,R) - min(L, … ,R)+1 = R - L + 1

然后可以转化为 r = max - min + l

枚举左端点 l,得到左边的最大值 maxl 和最小值 minl,求得右边第一个大于 maxl 的位置 minr 和第一个小于 minl 的位置maxr

分类讨论:

1.r ∈ [mid + 1, min(maxr, minr) - 1], 即最值都在左边,判断 maxl - minl + l 是否在范围内

2.r ∈ [min(maxr, minr), max(maxr, minr)] , 即最值一个在左边一个在右边。

假设 maxr > minr, 则最小值与左边无关,处理出 mid + 1 ~ r 之间每个点的前缀最小值,判断 r ~ max 的范围和 l ~ min 的区间交

3.maxr < minr 同理,求前缀最大值

4.r ∈ [max(maxr, minr), R] , max - min 随 r 增大而变大,求区间交

然后递归处理子区间

XOR最小生成树

• 给定 n 个点,第 i 个点的点权是 a[1…n],现在定义边 (i,j)的权值是 a[i] xor a[j],求最小生成树

将所有的数字排序,再用01字典树维护

用最高位不同将数字分开来,而内部数字则用同样的方法进行异或连边

区间统计

• 给定 a[1…n],求有⼏个区间 [L,R] 满⾜ a[L] or a[L+1]…or a[R]>max(a[L…R])
• N<=3*10^5
• a[i]<2^30

x = max 即对于可行区间,y or x = y

枚举最大值 x

统计 x 向左/向右 x or a[i] = x ,满足条件的 i 的最大最小值

相乘求区间数

二分

• ⼆分其实是对答案分治

• 分数规划问题
有一些二元组(ai,bi),从中选取一些二元组,使得∑ai/∑bi最大(最小)

每次二分 mid,判断∑ai/∑bi >= mid

转化为:∑(a[i]−b[i]∗mid)>=0

然后check贪心

• 给定 n 个点 x[1…n],要求将它划分成尽量少的连续区间,使得每个区间的最小圆覆盖的半径<=S

求最小覆盖圆是O(n)的

所以 check(l,l + 2i) 找到二分的上界,再进行二分

复杂度为 O(n log n)

整体二分

• 类似分治,所有询问一起做

K大数查询

ZJOI

• 有 N 个位置, M 个操作,每次操作是 1 a b c,或者 2 a b k

• 1 a b c 表示在第 a 个位置到第 b 个位置每个位置都加入⼀个数 c

• 2 a b k 表示询问第 a 个位置到第 b 个位置的第 k 大的值

• N,M,c<=50000

二分 mid,判断每个询问答案是否≤mid

每个询问 K 小值 ≤mid

即 ≤mid 的数有没有 K 个

当遇到的操作是加入操作时,把要加入的数和mid比较

用树状数组维护每个被修改区间的 c 的个数

CDQ分治 [坑]

• 把 [L,R] 分成 [L,mid] 和 [mid+1,R]

• 考虑左边对右边的贡献

• 三维偏序
• 矩阵加,矩阵求和
• 缺 1 背包问题:给定 n 个物品的重量 W[i] 和价值 V[i], Q次询问,每次询问对除了第 i 个物品以外的物品 01 背包后重量不超过 S 的最大价值和
n,W,V<=2000. Q<=1000000
• 缺点最短路问题:给定 n 个点的带权无向图, Q 次询问,每次询问 X 到 Y 的不经过 Z 的最短路长度
N<=200, Q<=1000000
• 解递推式 f[n]=sum( f[i]*g[n-i] )

点分治[坑]

• 区间分治的复杂度保证是由于每次分成<=n/2的区间

• 树每次分成<=n/2的⼦树

• 点分治,是一种针对可带权树上简单路径统计问题的算法。

• 分治点一般为重心

• 每一次找到重心,递归的子树大小是不超过原树大小的一半的,那么递归层数不会超过O(logn)O(logn)层,时间复杂度为O(nlogn)

• 求所有边数<=L 的链的权值之和
• 给定⼀棵树,有 Q 次询问,每次询问离 x 距离 <=L 的点数
• 给定⼀棵树,每个点有物品重量 W[i] 和价值 V[i],求价值最大的重量不超过 S 的连通块, n,S<=2000

图论

图论基础术语

• 出度,⼊度,度数

• ⽆向图,有向图,欧拉回路,哈密尔顿回路,环,简单环

• 连通块,强连通块,点双连通分量,边双连通分量

• 深度优先搜索,⼴度优先搜索

BFS

• 给定⼀张有向图,每条边的⻓度为 1,求 1 号点到其他点的最短路⻓度
• 给定⼀张有向图,每条边的⻓度为 0 或 1,求 1 号点到其他点的最短路⻓度
• 给定⼀张有向图,每条边的⻓度为 1 或 2,求 1 号点到其他点的最短路⻓度

bfs直接做就可以了

Dijkstra

原理:当前 d[x] 最小的 x ⼀定已经确定了最短路

扩展:当 dis[x] 的大小在 10^7 内时怎么做

把优先队列换成链表 把log强行去掉

• 缺点:图中不能有负权

Bellman-Ford算法

适用前提:没有负环(或称为负权值回路),但可以有负权

可以用来判断是否有负权回路

SPFA 算法

• ⽤⼀个队列维护有哪些点等待更新,优化了Bellman-Ford

• 每次取出⼀个点 x 去更新所有出边 (x,y,w),如果 y 被更新了就压⼊队列

• 时间复杂度: O(nm)

(如何卡SPFA算法:搞个⾏很少的⽹格图,竖着的边权很⼩,横着的边权很⼤)

具体可见https://blog.csdn.net/yfzcsc/article/details/77623365

判断是否存在负环

• 判断最短路的边数是否>n

• 判断⼀个点是否⼊队超过 n 次

Floyd 算法

• 给定⼀张 n 个点 m 条边的正权有向图,求每两个点之间的最短路

• 设 F(K,X,Y) 表示 X 到 Y 的路径中,满⾜路径上的点的标号都不超过 K 的最短路径

• F(K,X,Y)=Min( F(K-1,X,Y) , F(K-1,X,K)+F(K-1,K,Y) )

• 时间复杂度: O(n^3)

差分约束问题

• 最短路问题的约束:

• 对于 (x,y,w), d[y]<=d[x]+w

• 最短路问题可以给出这⼀类不等式的最⼤解

次短路

• 如何求出 1 号点到 N 号点的次短路

• 定义:若 d[v]=d[u]+w(u,v),则称 (u,v) 是最短路图上的边

• ⼀条次短路⼀定⾄多经过⼀条⾮最短路图上的边

[NOIP2017] 逛公园

• 给定⼀张有向带正权拓扑图,求有几条 1 到 N 的路径的长度<= 1 到 N 的最短路+K
• N,M<=105, K<=100,边权<=109

dis[i] 表示 从 1 号点到第 i 号点的最短路

f[x][L] 表示当前走到节点x,还能在原先最短路的基础上多走L

f[x][L]中 L 的有效取值为dis[1,x] ~ dis[1,x] + k,共k + 1 种

然后DP

要注意过程中还要用spfa判环

最短路变种

• 给定⼀个带权有向图, Q 次询问,每次询问删掉某条边后 1到 n 的最短路

如果删去的边不是在原图的最短路上的,则没有影响

而如果删去的边是在最短路上的,我们可以先预处理出一条左端点在这条边的左端点前,右端点在这条边的右端点后的边,且长

度最小

• 给定⼀个带权有向⽆环图, Q 次询问,每次询问删掉某个点后 1 到 n 的最短路

强连通分量

• 在做 Tarjan算法时,如果 tarjan(x) 后发现 dfn[x]=low[x],则x 的⼦树⾥的剩下的所有点构成⼀个强连通分量

数环

• 给定⼀张 n 个点 m 条边的⽆向图,求三元环个数

• 给定⼀张 n 个点 m 条边的⽆向图,求四元环个数

• n,m<=50000

最小生成树

• 给定⼀张 n 个点的带权⽆向图,求权值和最⼩的⽣成树

• Kruskal 算法:将边按照权值⼤⼩从⼩到⼤排序,之后能加就加,⽤并查集维护

• 证明:证明权值最⼩的边⼀定在最⼩⽣成树中,然后归纳法

• 你现在很想知道⼀个数列 A[1…N] 是啥,但是需要花费代价去获取情报,你可以花费 Cost[L][R] 的值去得到 A[L…R]的和,给定 Cost,求最少花费多少代价才能确定 A[1…N]
• N<=1000, Cost[L][R]<=109

Prufer序列

• 将⼀棵树变成⼀个序列:

• 每次选择树上标号最⼩的叶⼦,删掉它,将与它相连的那个点的标号加到序列⾥,直到只剩下 2 个点

• 可以证明:任意⼀个⻓度为 n-2 的 1…n 的序列都是某棵树的 Prufer 序列

• 所以可以推出: n 个点的⽆根树个数为 n(n-2)

• 每一个Prufer序列和一棵树双向映射

• 给定每个点的度数 d[i],求有几棵这样的无根树。

假设一个点入度为d,它最多有可能在prufer上出现(d-1)次

一共有n-2个数字出现在prufer上,其中每个相同数字出现d-1次,所以答案为(n - 2) ! / ( (d1 - 1)! (d2 - 1)! ……(dn - 1)! )

⼆分图[坑]

• 可以分成两部分,使得这两部分内部没有边的图

• ⼀个图是⼆分图等价于该图没有奇环

• prob1. 判断⼀张图是否有奇环

O(N)

• prob2. 判断⼀张图是否有偶环

最⼩顶点覆盖:选最少的点覆盖所有边

|⼆分图最⼩顶点覆盖| = |⼆分图最⼤匹配|

最⼤独⽴集:选最多的点使得它们两两没边相连

|⼆分图最⼤独⽴集| = 总点数 - |⼆分图最⼩顶点覆盖|

Hall 引理[坑]

• 设 S 是左边点的⼀个⼦集,设 N(S) 为 S 所有点邻居的并集,则⼀个⼆分图存在完美匹配的充要条件是:

• 对于所有 S, |S|<=|N(S)|

• 给定⼀个 [n,n] 个点的⼆分图,每条边有边权,要求删去边权和最⼩的边集,使得这张图没有完美匹配
• n<=18

选择

• 给定 n 个数对 (x[i],y[i]),你需要构造⼀个数组 s[i],满⾜ s[i]是 x[i] 和 y[i] 中的其中⼀个,且 s ⾥没有重复元素,顺便数个⽅案数
• 1<=n<=10^6

边的染⾊

• 给定⼀张⽆向图,边有边权且为0或1,有些边的边权还没有确定,现在需要你确定这些边的边权,使得满⾜所有环的边权的异或值都为0,求⽅案数
• 1<=n,m<=10^5

边权转点权

存在a[1…N] 对于(x,y,w) 有a[x] xor a[y] = w

S:已确定的边构成的连通块个数

• 有⼀个 N * M 的矩形,其中有 K 个格⼦中有病毒,现在你可以进⾏若⼲次消毒,每次你可以选择⼀个任意⼤⼩的⼦矩形进⾏消毒,假设是 A *B 的矩形,则代价是 min(A,B),要求你⽤最少的代价进⾏消毒
• N,M,K<=5000

字符串[坑]

KMP算法

• fail[N]: s[1…N] 最⻓的相等的前后缀

• bobocow:

• fail=[0,0,1,2,0,0,0]

• 求⼀个串的最⼩循环节 , = N - fail[N]

对于所有i, 有s[i] = s[i - p]

NOIP2014 动物园

• 给定⼀个字符串 S,对于每个前缀S[1…i]求出:有⼏对前后缀相等且不重叠. |S|<=1000000

GT考试

• 给定⼀个 m 位数字串 S,求有⼏个⻓度为 n 的字符串 T,满⾜ S 不是他的⼦串. m<=20. n<=10^9
• 有⼀个串 S,给定 S[1…i] 的最⼩循环节 d[i],构造⼀个字典序最⼩的S. |S|<=10^6
• 有⼀个串 S,定义⼀个优秀的拆分是将⼀个串表示成 AABB 的形式,求 S 的所有连续⼦串的优秀的拆分的个数之和. |S|<=2000
• Trie上的KMP: AC⾃动机

后缀数组【巨坑,先放着】

• 给定⼀个串 s[1…n],将所有后缀排序

• rk[i]: s[i…n] 的排名

• sa[i]: rk 为 i 的后缀是哪个

• 倍增+归并排序实现

• height[i]: S[sa[i]…n] 和 S[sa[i+1]…n] 的LCP

• height[i]>=height[rk[sa[i]-1]]-1

后缀数组常规操作

• LCP(X,Y)=Min(H[rk[x]]…H[rk[y]-1])

• 最⻓重复⼦串

• 不可重叠最⻓重复⼦串

• 本质不同的⼦串个数

• 求 S[l…r] 的出现次数

总结

还是有很多的坑要填。

分治的话,CDQ啊,整体分治什么的都不是很理解

图论总体还好,毕竟基本学过,但二分图,hall引理等还有一些没怎么懂

字符串大写懵,后缀数组是毒瘤

还是多看看其他大佬的博客,加深理解吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值