• 正睿19暑期B班DAY2 分治x图论x字符串


    注 本文中max[l, r]表示区间[l, r]中最大值 min[l, r]同理

    Part 1 分治

    • 经典例题

    • 求所有区间的最⼤值之和

    一个最大值,对L在它左边R在它右边的所有区间都有贡献 O(n)

    • 求所有区间的最⼤值*最⼩值之和

    对于一个区间|L --- mid --- R|

    处理出[mid, R]中(min,max,min*max)的前缀和

    然后对于(L leq i leq mid) 处理(Ma[i])表示对于(mid leq j leq Ma[i]) 有[i, j]中最大值为[i, mid]的最大值

    由于Ma[i]单调减 这个东西可以线性处理 (Mi[i])同理

    于是对于以下情况:|L-----i------mid---Mi[i]-----Ma[i]---R|(Ma[i]小的话也同理)

    对于区间[l, r]如果(L leq l leq mid, mid + 1 leq r leq Mi[i]) 每个贡献为min[i, mid] * max[i, mid]

    对于区间[l, r]如果(L leq l leq mid, Mi[i] + 1 leq r leq Ma[i]) 贡献用min前缀和计算

    对于区间[l, r]如果(L leq l leq mid, Ma[i] + 1 leq r leq R) 贡献用min*max前缀和计算

    (O(n log n))

    • 求所有区间的 gcd 之和

    因为一个玄学结论一个区间gcd不同的分段个数期望为(log(len))

    所以就暴力分治就好啦(惊辽)(O(n log^3 n))

    • 求⼆维平⾯上最近点对

    先按照x坐标排序 中间切(假设是竖着切)

    若递归得到的答案为ret

    那么只需计算可能更新答案的点

    在中间的切线两侧取水平宽ret 竖直高2*ret的矩形

    计算该矩形中跨线点对就好啦

    又有一个玄学结论说这个矩形中 中线的一侧期望有6个点

    。。。

    好吧

    常数估计巨大?(O(n log n))

    • 分治多项式乘法

    就是拆成两份分开乘啦


    • 旅⾏者

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

    • 1<=n*m,Q<=50000

    把询问离线 如果竖着长就横着切 反之亦然

    然后对于中间线上每个点做一次单点最短路

    然后更新询问 注意递归进来的所有询问都要处理 不只是跨线的

    (O(S sqrt{S} log sqrt{S}))


    • 连续区间

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

    • n<=500000

    如果要区间[l, r]连续 那么等同于(max[l, r] - min[l, r] = r - l)

    类似于经典问题2

    对于一个区间|L --- mid --- R|

    然后对于(L leq i leq mid) 处理(Ma[i])表示对于(mid leq j leq Ma[i]) 有[i, j]中最大值为[i, mid]的最大值

    对于区间[l, r]如果(L leq l leq mid, mid + 1 leq r leq Mi[i]) 合法右端点要求(r = l + max[l, mid] - min[l, mid])

    对于区间[l, r]如果(L leq l leq mid, Mi[i] + 1leq r leq Ma[i]) 合法右端点要求(r - max[l, mid] = l + min[mid + 1, r])

    对于区间[l, r]如果(L leq l leq mid, Ma[i] + 1 leq r leq R) 合法右端点要求(r - max[mid + 1, r] + min[mid + 1, r] = l)

    等式左边的东西处理一下就OK啦 (O(n log^2 n ))


    • XOR最⼩⽣成树

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

    relaxing啊,按照最高位向下划分就好啦


    • 区间统计

    • 给定 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

    预处理一个数a[i]左边第一个a[j]满足a[j] | a[i] != a[i]显然这个东西有单调性

    然后如经典例题1来操作就好啦 (O(n) + O(n log n) = O(n log n))


    Part 2 ⼆分与分治

    • 经典例题

    • 分数规划问题

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

    众所周知,最小圆覆盖是一个(O(n))算法【雾】

    然而直接二分是会被卡的 所以采用一种神奇的方式

    (check[l, l + 2^1]),然后是(check[l, l + 2^2])一直找到(check[l, l + 2^i])不能被合法圆覆盖了

    有了范围再二分 (O(n log n))

    • 给⼀个序列 a[1…n],要求选出恰好 K 个互不相交的区间, 使得权值之和最⼤

    (被咕掉了。。)安利bzoj TREE


    • 整体⼆分

    • 有 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

    如题,整体二分。。
    右转[CTSC2008]网络管理


    • CDQ分治

    • 三维偏序

    • 矩阵加,矩阵求和

    • 缺 1 背包问题:给定 n 个物品的重量 W[i] 和价值 V[i],Q次询问,每次询问对除了第 i 个物品以外的物01 背包后重量不超过 S 的最⼤价值 n,W,V<=2000. Q<=1000000

    分治(solve(l, r, f_{l, r}))

    (f_{l, r})表示除去[l, r]的背包结果

    • 缺点最短路问题:给定 n 个点的带权⽆向图,Q 次询问,每次询问 X 到 Y 的不经过 Z 的最短路⻓度,N<=200,Q<=1000000

    floyd第一维分治,与上一题的状态类似,(solve(l, r, f_{l, r}))

    • 解递推式 f[n]=sum( f[i]*g[n-i] )(雾)


    • 点分治

    • 求所有边数<=L 的链的权值之和

    • 给定⼀棵树,有 Q 次询问,每次询问离 x 距离 <=L 的点数

    • 给定⼀棵树,每个点有物品重量 W[i] 和价值 V[i],求价值最⼤的重量不超过 S 的连通块,n,S<=2000


    • 时间分治 (被咕掉了)

    • 加边删边询问两个点是否连通


    Part 3 图论

    • dijkstra当 dis[x] 的⼤⼩在 10^7 内时怎么做?

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


    • 如何卡SPFA算法

    • 搞个⾏很少的⽹格图,竖着的边权很⼩,横着的边权很⼤


    • [noip2016]逛公园

    • 给定⼀张有向带非负权有环图,求有⼏条 1 到 N 的路径的⻓ 度<= 1 到 N 的最短路+K

    (N,M<=10^5,K<=100,边权<=10^9)


    • 最短路变种

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

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


    • 数环

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

    1564400687456.png

    把所有点按照度数从小到大排序

    然后从小点向大点连边(终点集为D[i], 原图中终点集为G[i])

    如果有三元环的话状态如图所示(假装从小到大是x, y, z)

    所以就

    $for i = 1 to n (维护)res[x][i]$ ((res[x][i])表示有边(x -> i))

    (for x = 1 to n) for(int y : D[x]) for(int z : D[y]) ans += $res[x][z] $

    (O(m sqrt{m}))

    据说bzoj3498是板子

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

    • n,m<=50000

    1564402331429.png

    还是排序连边 四元环只会有上图三种情况(假设从小到大为a, b, c, d)

    发现这两种情况 都是从a先走一条有向边 再走一条无向边

    (for x = 1 to n) for(int y : D[x]) for(int z : G[y]) (ans += res[x][z], ++res[x][z];)

    (O(m sqrt{m}))


    • 圈套圈算法

    • 任选⼀个起点,从起点开始 dfs,每条边只能被⾛⼀遍,当没有边可以⾛的时候把 x 压⼊答案的队列中

    • 最后的答案是反着的欧拉回路


    • 树:N 个点 N-1 条边的连通⽆向图,分为有根树和⽆根树

    • 树的叶⼦:度数为 1 的点


    • 最⼩⽣成树

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

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

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

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

    • N<=1000,Cost[L][R]<=10^9

    每个区间[l, r]看作(edge(l - 1, r, cost[l][r]))

    然后(装作以0为根)最小生成树就好了


    • Prufer序列

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

    • 每次选择树上标号最⼩的叶⼦,删掉它,将与它相连的那

    个点的标号加到序列⾥,直到只剩下 2 个点

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

    的 Prufer 序列

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

    例题:给定每个点的度数 d[i],求有⼏棵这样的⽆根树。

    (frac{(n - 2)!}{prod_{i = 1}^{n} (d[i] - 1)!})

    扩展安利:
    明明的烦恼

    本题相当于问根据给出的度数 有多少种prufer序列可以被生成
    对于一个度数为x (x >= 2) 的点 显然它要在prufer序列里占x - 1个位置
    于是这就变成了一道数学题

    本题公式

    [ans = binom{n - 2}{sum} frac {sum!} {prod limits_{i = 1}^{n} d[i] - 1} * (n - cnt)^{n - 2 - sum} ]

    本题难点其实是高精度qvq

    • ⼆分图

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

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

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

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


    • ⼆分图

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

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

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

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


    • Hall 引理

    • 设 S 是左边点的⼀个⼦集,设 N(S) 为 S 所有点邻居的并

    集,则⼀个⼆分图存在完美匹配的充要条件是:

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

    • Hall 定理的应⽤

    • 给定⼀个 [n,n] 个点的⼆分图,每条边有边权,要求删去边

    权和最⼩的边集,使得这张图没有完美匹配

    • n<=18

    这道题没有多项式算法 只能枚举左边的子集 暴力Hall


    • 选择

    • 给定 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

    设一个边的边权为两端点权异或和

    然后环上的异或和必然为零啦

    因为每个点权被计算了两次


    • 练习题

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

    • N,M,K<=5000

    行列建点 最小点覆盖等于最大匹配

    Part 4 字符串

    • 例题

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

    右转NOI动物园


    • 给定⼀个 m 位数字串 S,求有⼏个⻓度为 n 的字符串 T,满⾜ S 不是他的⼦串. m<=20. n<=10^9

    模拟fail,矩阵乘法加速


    • 有⼀个串 S,给定 S[1…i] 的最⼩循环节 d[i],构造⼀个字典序最⼩的S. |S|<=10^6

    对于第i位,若S[i]使得fail[i] > d[i]那么S[i]就不能用 要大一点


    • 有⼀个串 S,定义⼀个优秀的拆分是将⼀个串表示成 AABB 的形式,求 S 的所有连续⼦串的优秀的拆分的个数之和. |S|<=2000

    骗分般优秀的拆分 从中间分开统计pre[i] (AA个数)+ suf[i + 1](BB个数)
    至于pre的预处理 hash暴力就好啦


    • Trie上的KMP:AC⾃动机


    • 后缀数组常规操作

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

    • 最⻓重复⼦串

    (height[ ]_{max})

    • 不可重叠最⻓重复⼦串

    二分一个长度 用height check一下

    • 本质不同的⼦串个数

    (n(n + 1) / 2 - sum_{i = 1}^{n} height[i])

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

    从l向下找有多少个(height[i] >= r - l + 1)

  • 相关阅读:
    Excel中substitute替换函数的使用方法
    如何在Excel中提取小数点后面的数字?
    提升单元测试体验的利器--Mockito使用总结
    SpringMVC项目读取不到外部CSS文件的解决办法及总结
    java8 Lambda表达式的新手上车指南(1)--基础语法和函数式接口
    Spring-data-redis操作redis知识总结
    优雅高效的MyBatis-Plus工具快速入门使用
    Thrift入门初探(2)--thrift基础知识详解
    Thrift入门初探--thrift安装及java入门实例
    spring事件驱动模型--观察者模式在spring中的应用
  • 原文地址:https://www.cnblogs.com/hjmmm/p/11266286.html
Copyright © 2020-2023  润新知