专项测试 数据结构1


T1 Surprise me

式子懒得写,写几个比较重要的地方吧

\(\phi(a* b)=\frac{\phi(a)* \phi(b)* \gcd(a,b)}{\phi(\gcd(a,b))}\),就把\(\phi(x)=x\prod_{p|x}\frac{p-1}{p}\)代进去就行了

然后枚举gcd=d,出来一个恰好的形式长这样

\[\sum_{i=1}^{n}\sum_{j=1}^{n}[\gcd(a_i,a_j)=d]* \phi(a_i)* \phi(a_j)* dis(i,j) \]

这个记为f[d]

然后莫反,\(F_x=\sum_{x|d}f_d,f_x=\sum_{x|d}F_d*\mu(\frac{d}{x})\)

那么这个F[x]就能写成至少的形式

\[\sum_{i=1}^{n}\sum_{j=1}^{n}[d|\gcd(a_i,a_j)]* \phi(a_i)* \phi(a_j)* dis(i,j) \]

把d的倍数取出来建虚树,然后树形dp就行了

T2 神牛养成计划

拿哈希过的,,

O(nm)是过不去的(反正我过不去)

就剪剪枝,拿个map,mp[i]存前缀哈希为i的映射值,映射到vector上存串的下标

然后前缀已经配好了,数一数这些串的后缀几个能配上就行了

正解还是很多的,其中之一

按前缀排序,那么前缀能匹配上的串区间二分就行了,匹配后缀就可持久化trie,然后把询问后缀串放trie上跑。

题解给的复杂度是\(O(m\log n+L1+L2)\),要是我写,L1得带个log(拼一块后缀数组)

T3 串

考虑维护\(c_i\)表示以 i 为右端点的子串最大值,拿个优先队列存(i,c[i]),每次取队头,再插入(i,c[i]的次大值)

问题变成了维护\(c_i\),查询次大值转换成支持删除和查询区间最大值,不难想到线段树

可持久化一下就行了,i-1->i时,只需将\([last_{a_i}+1,i]\)加上a[i]