07 2020 档案

摘要:这道题的字符集是 \(O(n)\) 的,正常的子序列自动机时空复杂度都无法接受。 所以我们考虑用 \(vector\) 来代替这个过程。用 \(vector\) 记录每个字符出现的位置,然后进来一个字符就二分这个字符下一次出现的位置。时间复杂度 \(O(nlogn)\)。 代码: #include< 阅读全文
posted @ 2020-07-30 16:33 With_penguin 阅读(114) 评论(0) 推荐(0)
摘要:OI Wiki 子序列自动机的每个状态表示当前位置结尾的字符串中第一次出现的字符串。状态数 \(n+1\) ,转移数 \(O(n\times \sum)\),其中 \(n\) 为字符串长度,\(\sum\) 为字符集大小。 应用 判断一个字符串是否是另一个字符串的子序列 对第二个序列建立子序列自动机 阅读全文
posted @ 2020-07-30 16:30 With_penguin 阅读(749) 评论(0) 推荐(0)
摘要:最小表示法模板题: 代码: #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=300009; int n,a[N]; void init 阅读全文
posted @ 2020-07-30 13:23 With_penguin 阅读(126) 评论(0) 推荐(0)
摘要:OI WIki 找出一个字符串的最小循环同构,就是最小表示法。 由于我们只想要找到最小的,所以可以用打擂台的方式进行筛选。但是如果每个串都逐位比较的话,发现会被 \(aaa\cdots aab\) 这样的数据轻松卡成 \(O(n^2)\)。 考虑优化,我们发现如果有两个相同的很长的子串,复杂度就难以 阅读全文
posted @ 2020-07-30 13:21 With_penguin 阅读(155) 评论(0) 推荐(0)
摘要:还是求几个串的最长公共串。 但是由于数据范围的原因,用后缀数组可能会T,所以现在介绍一种后缀自动机的解法。 首先考虑两个串的公共串怎么求(假设分别为 \(S\)、\(T\))。对 \(S\) 建立后缀自动机,把 \(T\) 放在后缀自动机上跑,如果没有转移就跳后缀 \(link\)。然后在每个节点记 阅读全文
posted @ 2020-07-22 23:38 With_penguin 阅读(88) 评论(0) 推荐(0)
摘要:对最外层所有叶子编号(编号都为 $1$),然后把他们删去,然后给倒数第二层叶子编号(编号都为 $2$)。以此类推。 对于每一种编号考虑,由于一条路径最多只能覆盖两个编号相同的节点,所以最后答案为 \(\sum\limits_{i=1}^{k}\max(2\times L,sum[i])\)。其中 \ 阅读全文
posted @ 2020-07-22 23:27 With_penguin 阅读(126) 评论(0) 推荐(0)
摘要:对 \(T\) 的每个位置进行考虑。 设 \(f_i\) 表示以 \(T\) 的第 \(i\) 个位置结尾的字符串(\(S_k\))的个数 设 \(g_i\) 表示以 \(T'\) 的第 \(n-i+1\) 个位置结尾的字符串(\(S_k'\))的个数(其中 \(T'\) 表示 \(T\) 的反串, 阅读全文
posted @ 2020-07-22 22:49 With_penguin 阅读(117) 评论(0) 推荐(0)
摘要:首先把这些串排成一排(中间用随便什么符号隔断一下),然后跑一遍后缀数组。 我们把这些后缀排序后,发现一段区间可以对答案有贡献当且仅当 \(n\) 个字符串的任意位置都在这个区间出现过,然后 \(two\_point\) 跑一遍,可以用你喜欢的数据结构维护 \(height\) 的最小值。 代码: # 阅读全文
posted @ 2020-07-19 23:16 With_penguin 阅读(171) 评论(0) 推荐(0)
摘要:OI Wiki 一些重点: 后缀自动机形成的图是一个DAG(许多题可以利用这个性质DP) 这个DAG上的任意一条路径是一个子串 endpos等价类可以由parent树的子树合并得到(再加上这个节点本身) 注意后缀自动机的源点代表空串,很多题需要单独处理 例题: luogu P3804 【模板】后缀自 阅读全文
posted @ 2020-07-19 23:09 With_penguin 阅读(89) 评论(0) 推荐(0)
摘要:当 \(t=0\) 时:考虑 \(dp[i]\) 表示到了后缀自动机上的点 \(i\),往后走还能形成多少子串。转移很显然:\(dp[i]=1+\sum dp[nxt_i]\)。加一是因为可以直接停下,\(nxt_i\) 代表 \(i\) 到 \(nxt_i\) 有一条边。然后想主席树之类的查询就可 阅读全文
posted @ 2020-07-19 23:08 With_penguin 阅读(112) 评论(0) 推荐(0)
摘要:每个子串的出现次数就是其后缀自动机上所在节点的endpos等价类集合的大小。 代码: #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N= 阅读全文
posted @ 2020-07-19 22:57 With_penguin 阅读(123) 评论(0) 推荐(0)
摘要:这篇文章写的贼好 例题: P4688 [Ynoi2016]掉进兔子洞 题解 阅读全文
posted @ 2020-07-16 11:20 With_penguin 阅读(109) 评论(0) 推荐(0)
摘要:bitset优化莫队。 由于bitset并不能存可重集,所以我们考虑给每种元素在bitset里留 \(k\) 个位置(\(k\) 为这种元素的个数)。我们只需要在离散化的时候不去重,然后把 \(p\) 放进bitset中第 \(p-cnt_p\) 个位置就行了(\(cnt_p\) 为bitset当前 阅读全文
posted @ 2020-07-16 11:18 With_penguin 阅读(120) 评论(0) 推荐(0)
摘要:魔改最小斯坦纳树的题。。。 首先我们发现颜色太多了非常不好处理,一种套路是随机把这些颜色映射到 \(k\) 种颜色,随机很多次来保证正确性。最后的正确率大概是: \[ 1-(1-\frac{k!}{k^k})^C \] 其中 \(C\) 为随机次数。 好了现在我们只有 \(k\le 7\) 种颜色了 阅读全文
posted @ 2020-07-15 23:24 With_penguin 阅读(97) 评论(0) 推荐(0)
摘要:字典树 Trie的维护可以看做一个自底向上的更新,每次更改值时只关注叶子节点,有叶子节点逐层向上更新。 例题: luogu P6018 [Ynoi2010]Fusion tree 题解 luogu P6623 [省选联考 2020 A 卷] 树 题解 阅读全文
posted @ 2020-07-14 21:31 With_penguin 阅读(103) 评论(0) 推荐(0)
摘要:考试前几天刚刚考了01trie整体加一这个trick,但是我当时口胡没写。考场上乱写写了一年没写对。。。 这个题的做法就是对每个点维护一个01trie,然后每次向上合并就啥也没有了。 代码: #include<cstdio> #include<cstring> #include<iostream> 阅读全文
posted @ 2020-07-14 21:30 With_penguin 阅读(119) 评论(0) 推荐(0)
摘要:之前膜你赛好像考过好几次这种类型的题目,但我太菜了一直没听懂。 有个很常见的trick是统一维护一个点所有儿子的异或和,单独维护父亲。然后再上能维护全局+1的01trie这题就做完了。 代码: #include<cstdio> #include<cstring> #include<algorithm 阅读全文
posted @ 2020-07-14 21:19 With_penguin 阅读(153) 评论(0) 推荐(0)
摘要:首先最小斯坦纳树求出连接所有重要情报站的最小代价。 然后状压每个频道做一遍子集DP就完事了。 代码: #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #include< 阅读全文
posted @ 2020-07-13 00:06 With_penguin 阅读(102) 评论(0) 推荐(0)
摘要:给定一个包含 \(n\) 个点和 \(m\) 条边的无向联通图 \(G=(V,E)\)。 再给定包含 \(k\) 个结点的点集 \(S\),选出 \(G\) 的子图 \(G'=(V',E')\),使得: \(S\subseteq V'\); \(G'\) 为连通图; \(E'\) 中所有边的边权和最 阅读全文
posted @ 2020-07-12 22:02 With_penguin 阅读(384) 评论(0) 推荐(0)
摘要:代码: #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> using namespace std; const int N=109,INF=1<<30; int n,m, 阅读全文
posted @ 2020-07-12 21:59 With_penguin 阅读(175) 评论(0) 推荐(0)
摘要:容易发现这就是后缀排序后连续 \(k\) 个后缀的 \(lcp\) 的最小值的最大值,用单调队列跑一遍 \(height\) 数组即可。 代码: #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #in 阅读全文
posted @ 2020-07-12 20:37 With_penguin 阅读(152) 评论(0) 推荐(0)
摘要:对每一条边单独考虑其贡献。 我们现在想算有多少连续区间跨过了这条边。正难则反,我们考虑有多少连续区间不跨过这条边,最后用总的减去这些。所以我们只需要计算当前子树内和子树外的连续区间的贡献就行。 考虑 dsu on tree。子树内用并查集维护并计算极长子段的贡献,子树外用set维护其补集并计算贡献即 阅读全文
posted @ 2020-07-12 14:56 With_penguin 阅读(230) 评论(0) 推荐(0)
摘要:考虑点分治。 考虑如何合并线段 \(\sum\limits_{i=1}^{n}i\times a[i]\) 和 \(\sum\limits_{j=1}^{m}j\times b[j]\)。新线段的表达式 \(\sum\limits_{i=1}^{n}i\times a[i] + \sum\limit 阅读全文
posted @ 2020-07-11 20:58 With_penguin 阅读(123) 评论(0) 推荐(0)
摘要:首先考虑判断两个点 \(a,b\) 在一个询问 \((l,r,x)\) 下连通:\(path(a,b)\) 上的点的编号都在 \(l \sim r\) 之间,可以用倍增预处理。 对原树建立点分树。对于每个询问 \((l,r,x)\),我们考虑找到这样一个点: 这个点是 \(x\) 在点分树上的祖先 阅读全文
posted @ 2020-07-11 17:31 With_penguin 阅读(133) 评论(0) 推荐(0)
摘要:闲聊 看到树上路径问题点分治肯定可以做 看了一下其他题解好像没有具体介绍如何不重不漏地计数以及一些细节(其实是我太菜了没看懂 蒟蒻我做点分题还没有用过容斥定理,一般都是在每颗子树里跑一遍的时候直接累加前面已经跑过的贡献QWQ 前置芝士 点分治 平衡树(其实可以不用,但因为我不太会容斥,而且这题边权比 阅读全文
posted @ 2020-07-10 06:20 With_penguin 阅读(189) 评论(0) 推荐(0)
摘要:强行把李超线段树搬到树上。然后这题我调了两天,最后发现数组开小了。。。 我们发现题目就是把凸包放到树上然后求最值。用树剖把树化为序列,然后直接李超线段树就可以了。 惨痛的教训:一共插入的线段数量是 \(O(nlogn)\) 级别的,数组一定要开大/lb。 代码: #pragma GCC optimi 阅读全文
posted @ 2020-07-08 01:13 With_penguin 阅读(217) 评论(0) 推荐(0)
摘要:我竟然为这题的函数不能拆成完成积性函数想了两个小时(捂脸)。 看到这么大的数据范围和求前缀和的要求,我们首先想到了Min_25筛。 设 \(f(i)=\sigma_0(i^k)\),则 \(f(p^e)=ke+1\)。 啊啊啊这个 \(f\) 没有办法拆成完全积性函数,所以我们就求不了 \(f\) 阅读全文
posted @ 2020-07-06 06:21 With_penguin 阅读(160) 评论(0) 推荐(0)
摘要:代码: #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cmath> using namespace std; typedef long long LL; const int M=1 阅读全文
posted @ 2020-07-05 21:33 With_penguin 阅读(152) 评论(0) 推荐(0)
摘要:最小圆覆盖 主要是我太菜了不会证明qwq,上面的博客讲的非常好。 主要是存代码: #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> using namespace std 阅读全文
posted @ 2020-07-03 10:17 With_penguin 阅读(134) 评论(0) 推荐(0)
摘要:使用面积法与矢量叉积即可。 代码: #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; struct Point { double x,y; Point() {} 阅读全文
posted @ 2020-07-03 09:32 With_penguin 阅读(575) 评论(0) 推荐(0)