2020牛客暑期多校训练营

2020牛客暑期多校训练营

第一场出题人:叉姐

A B-Suffix Array: 后缀数组

连接
传送门: here
题意
n ( 1 e 5 ) n(1e5) 的字符串只包含 a b ab 两个字母,对它的 n n 个后缀字符串按 B B 函数来排序。
字符串的 B B 函数是一个向量, b i = m i n 1 < = j < i , s [ j ] = = s [ i ] ( i j ) bi=min_{1<=j<i,s[j]==s[i]}(i - j) html

思路
对于字符串的B值能够将他分红两部分求:
S=AD, 其中 A = aa…ab or bb…ba
A部分的B值为: 011…10
这是确保后缀S的D部分以前ab都出现过了,对D部分求出来的B值的顺序能够直接
参考后缀数组对整个字符串B值排序的答案。
因此我能够对每一个后缀记录三个值: one, isZero, sf
one: A部分中1的个数
isZero: A部分是否有最后一个0,便是否ab都出现了,便是否后面还有值
sf: D部分在后缀数组中的rank
对上面三个值从小到大排序以后的 id 即为答案。node

备注
叉姐说当只有两个字符时,有一个论文结论,对源字符串求出C值 ,
ci=min(j - i) 且 1<=i<j,s[j]==s[i],再末尾补上一个数 n+1 ,
而后对这个 C 值求后缀数组的 sa 反过来就是答案。git

AC_CODE
代码地址github

B Infinite Tree: 虚树+DP

连接
传送门: here
题意
m i n d i v ( x ) mindiv(x) be the minimum divisor greater than 1 1 of n n .
δ ( u , v ) \delta(u, v) be the number of edges between vertices u u and v v
m = 100000 , w [ i ] < = 10000 m = 100000, w[i] <= 10000
ϕ \phi
m i n u ( i = 1 m w [ i ] δ ( u , i ! ) ) min_u(\sum_{i=1}^m w[i]*\delta(u, i!)) , u你本身任选,求最小值web

思路
建出虚树而后 dp 便可
虚树中1,2!,3!,…,n!间不会存在相邻两个点 lca 高度和 x! 的高度相同
可是会存在 x,y 的 lcadep 高度相同,他们的lca可能都是1根节点,可是确定不会是别的点还在同一条链上,
x ! = p 1 k 1 p 2 k 2 . . . p m k m x! = p1^{k1}*p2^{k2}...pm^{km}
从1到x!的路径长度为 i = 1 m k i \sum_{i=1}^m ki
从1到x!路径上相邻两点的倍数关系必定是km个pm, …, 直到k1个p1
x ! x! 的深度比 ( x 1 ) ! (x-1)! 的深度多 x x 的素因子次数和
x ! x! ( x 1 ) ! (x-1)! 的分界点必定是次数不相同的最大的素数数组

备注app

AC_CODE
代码地址svg

H Minimum-cost Flow: 最小费用最大流

连接
传送门: here
题意
n = 50 , m = 100 n=50, m=100
给你一个最小费用流图,边单位流量费用 c i ci Q ( 100000 ) Q(100000) 次询问,每次询问告诉你每条边的流量上限是 u v \frac uv (保证 1 \le 1 ),问要从源点 1 1 流一个单位流量到汇点 n n 的最小费用是多少。函数

思路
由于每条边的流量上限其实都是同样的,因此咱们首先预处理,把每条边的流量扩大 v u \frac vu 倍,这样全部流量上限都是 1 1 ,费用流每次增广的时候只会增广 1 1 的流量,而后记录下每次增广的花费,边只有 100 100 条,最多只会增广 100 100 次.
询问就是暴力枚举每一条增广路径看流量和是否知足条件,若某次增广的流量多了就截断多的部分,只取到恰好我要的流量,并算贡献。
复杂度就是 O ( m q ) = 1 e 7 O(m*q) = 1e7 恰好能够过.spa

好比你加个前缀和预处理,二分处理询问,这样复杂度就是 O ( q l o g ( m ) ) O(q*log(m))
固然能够更快,你能够 O ( 1 ) O(1) 算出答案来,复杂度就是 O ( q ) . O(q).

我这里算的复杂度没有把求 g c d gcd 算进去.

备注

AC_CODE
代码地址

I 1 or 2: 思惟拆点+带花树

连接
传送门: here
题意
n = 50 , m = 100 n=50,m=100
小明要求每一个点的度数为 d u [ i ] = 1 o r 2 du[i] = 1 or 2 , 问你是否存在这样一个边的子集
知足上述条件。
不存在自环,可能有重边
度数和必定要保证为偶数

思路
把一条边拆成两个点,把每一个点 u u 拆成 d u [ u ] du[u] 个点
e d g e > e 1 e 2 edge ->e1 e2
x > x 1 x -> x1
y > y 1 y 2 y -> y1 y2
( e 1 , e 2 ) , ( x 1 , e 1 ) , ( e 2 , y 1 ) , ( e 2 , y 2 ) (e1, e2), (x1, e1), (e2, y1), (e2, y2)
再跑通常图最大匹配
看是不是完备匹配
若是存在完美匹配的话,必定能够是每条边拆成两个点分别和两个端点拆成的 d u [ i ] du[i] 个点中的一个相匹配。
若是完备匹配的话,证实说有条件都知足。

备注
若是 d u [ i ] du[i] 等于任意 0 0 或者整数, 也是能够这样写的.
若是 d u [ i ] du[i] 等于 0 0 的话,至关于 i i 相邻的边拆成的两个点本身和本身相匹配.
扩展题号为HDU3551,VJUDGE上有我share的提交.

AC_CODE
代码地址


第二场出题人:高铭鸿

A All with Pairs: 建完AC自动机dfs一遍便可

连接
传送门: here
题意
n ( 1 e 5 ) , s i 1 e 6 n(1e5),\sum |s_i| \le 1e6
i = 1 n j = 1 n f ( s i , s j )    m o d    998244353 \sum_{i=1}^n\sum_{j=1}^nf(si,sj)\;mod\;998244353
f ( s , t ) f(s, t) as the maximum i i that satisfy s 1 i = t t i + 1 t s_{1\dots i} = t_{|t|-i+1 \dots |t|}

思路
为字符串 u u 找其余字符串的前缀和 u u 的后缀所产生的贡献。每一个节点保存字典树子树中 e n d    n o d e end\;node 信息。遍历 f a i l fail 链接树,前面遍历过的节点都是个人后缀为每一个字符串记录一下遍历到当前节点匹配的最长前缀便可。回溯时记得还原。

备注

AC_CODE
代码地址

H Happy Triangle: 动态开点线段树

连接
传送门: here
题意

  1. 插入一个x
  2. 删除一个x
  3. 询问是否有两个数能够和x造成三角形

思路
动态开点权值线段树
对于查询只有三种状况,x是三边之中最大的,x是三边之中第二大的,x是三边之中最小的
备注

AC_CODE
代码地址


第三场出题人:dreamoon


第四场出题人:蒋世彪


第五场出题人:不朽之夜


第六场出题人:李泽仁