文章目录
A - K-th Number
题意
n n n 个数组, m m m 个询问,查询数列 [ l , r ] [l,r] [l,r] 范围内第 k k k 的数
题解
主席树模板题,任意抄个板子都能过
对于原序列的每一个前缀 [ 1 ⋅ ⋅ ⋅ i ] [1···i] [1⋅⋅⋅i] 建立出一棵线段树维护值域上每个数出现的次数,则其树是可减的
证明:主席树的每个节点保存的是一颗线段树,维护的区间信息,结构相同,因此具有可加减性
B - Black Box
题意
给出数列 a [ ] 、 b [ ] a[]、b[] a[]、b[]
对于每个 b [ i ] b[i] b[i] 在数组 a [ ] a[] a[] 上查询 [ 1 , b [ i ] ] [1,b[i]] [1,b[i]] 上第 i i i 大的数
题解
主席树模板题,任意抄个板子都能过
同A题
注意每组数据间输出一个空行
C - The xor-longest Path
题意
定义树上一条路径的异或和为路径上所有边权异或和
求树上异或和最大的路径的异或和
题解
-
求树上路径的异或有一个常用的技巧‘
d i s ( x , y ) = ( d i s ( x , l c a ) ⊕ d i s ( l c a , 1 ) ) ⊕ ( d i s ( 1 , l c a ) ⊕ ( l c a , y ) ) = d i s ( 1 , x ) ⊕ d i s ( 1 , y ) dis(x,y)=(dis(x,lca) \oplus dis(lca,1)) \oplus(dis(1,lca)\oplus(lca,y)) =dis(1,x) \oplus dis(1,y) dis(x,y)=(dis(x,lca)⊕dis(lca,1))⊕(dis(1,lca)⊕(lca,y))=dis(1,x)⊕dis(1,y)
-
问题转化成找到两个异或和最大的 d i s ( 1 , x ) 和 d i s ( 1 , y ) dis(1,x) 和 d i s ( 1 , y ) dis(1,x)和dis(1,y)
将所有 $d i s ( 1 , i ) $ 的二进制数造一棵字典树,然后对于每一个 d i s ( 1 , i ) dis(1,i) dis(1,i),我们都用来求一次答案,从最高位开始贪。
我们从最高位开始,尽可能找和当前 d i s ( 1 , i ) dis(1,i) dis(1,i) 的这一位不同的数,假如有,那么就往字典树的那边走,同时答案的这一位变成 1 1 1,否则就往另一边走。
D - 病毒侵袭持续中
题意
给你一个文本串 S S S 和 n n n 个模式串 T 1.. n T_{1..n} T1..n,请你分别求出每个模式串 T i T_i Ti 在 S S S 中出现的次数。
题解
AC自动机模板题,随便抄个板子都能过
- 把模式串构建成一棵Trie树
- 构建失配指针,适配指针指向当前节点所代表的串,最长的、能与后缀匹配的,在Trie中出现过的前缀所代表的节点
- 通过失配指针对匹配的字符串计数
E - Keywords Search
题意
给你一个文本串 S S S 和 n n n 个模式串 T 1.. n T_{1..n} T1..n,请求出在 S S S 中出现的模式串 T i T_i Ti 种类数
题解
AC自动机模板题,随便抄个板子都能过
同D
F - Chip Factory
题意
给出数组 s [ ] s[] s[],求 m a x i , j , k ( s i + s j ) ⊕ s k max_{i,j,k}(s_i+s_j)\oplus s_k maxi,j,k(si+sj)⊕sk
题解
观察数据 n ≤ 1000 n\leq 1000 n≤1000
我们可以枚举 i , j i,j i,j ,用 t r i e trie trie 树求与 ( s i + s j ) (s_i+s_j) (si+sj) 异或值最大的数
注意每次查询前在 t r i e trie trie 中删除 s i s_i si 和 s j s_j sj
G - Destiny
题意
给出数组 a [ ] a[] a[],查询 [ l , r ] [l,r] [l,r] 中出现次数大于 r − l + 1 k \frac{r-l+1}{k} kr−l+1 次的最小的数( k ≤ 5 k\leq 5 k≤5)
题解
注意到 k ≤ 5 k \leq 5 k≤5,
我们可持久化线段维护区间的个数,所以如果我们用 R R R 版本的数据减去 L − 1 L-1 L−1 版本的数据就是这个区间的数字个数
所以我们在主席树查询时,若该区间数字总数大于 r − l + 1 k \frac{r-l+1}{k} kr−l+1,即继续查询,优先询问左区间
因为 k ≤ 5 k \leq 5 k≤5,所以可以预见到我们同时查询左右两个区间次数最多只有两次,所以即便暴力查询,复杂度依旧为 l o g ( n ) log(n) log(n)
H - Zju2112 Dynamic Rankings
题意
动态维护区间第 K K K大
题解
带修主席树的模板题
使用树状数组套可持久化线段来解决。
每棵权值线段树 T ( i ) = ∑ j = i − l o w b i t ( i ) + 1 i a j T(i)=∑^i_{j=i−lowbit(i)+1}a_j T(i)=∑j=i−lowbit(i)+1iaj
这样每次修改 a i a_i ai 的时候都要修改对应的 O ( l o g n ) O(logn) O(logn)棵权值线段树,每次查询前缀和的时候都要求出 O ( l o g n ) O(logn) O(logn) 棵权值线段树对应节点的和。
I - 最大异或和
题意
维护数组 a [ ] a[] a[]
- 操作,在序列末尾添加一个 x x x
- 对于 l ≤ p , p ≤ r l\leq p,p\leq r l≤p,p≤r 查询 a [ p ] ⊕ a [ p + 1 ] ⋯ ⊕ a [ N ] ⊕ x a[p]\oplus a[p+1] \cdots \oplus a[N] \oplus x a[p]⊕a[p+1]⋯⊕a[N]⊕x 最大
题解
a [ p ] ⊕ a [ p + 1 ] ⋯ ⊕ a [ N ] ⊕ x = s [ p − 1 ] ⊕ s [ n ] ⊕ x a[p]\oplus a[p+1] \cdots \oplus a[N] \oplus x = s[p-1] \oplus s[n] \oplus x a[p]⊕a[p+1]⋯⊕a[N]⊕x=s[p−1]⊕s[n]⊕x
s i = a [ 1 ] ⊕ a [ 2 ] ⊕ ⋯ ⊕ a [ i ] s_i = a[1] \oplus a[2] \oplus \cdots \oplus a[i] si=a[1]⊕a[2]⊕⋯⊕a[i]
查询转化为求 p ∈ [ l − 1 , r − 1 ] p\in[l-1,r-1] p∈[l−1,r−1] ,使得 s [ p ] ⊕ ( s [ n ] ⊕ x ) s[p]\oplus (s[n]\oplus x) s[p]⊕(s[n]⊕x) 最大
构建一颗可持久化 0 / 1 T r i e 0/1 Trie 0/1Trie,第 i i i 个版本为插入了 s [ i ] s[i] s[i] 后的 T r i e Trie Trie 树。
每一个点维护一个 m a r k mark mark 表示上一次修改该节点的左边
在第 r − 1 r-1 r−1 课树上,只经过 m a r k mark mark 大于等于 l − 1 l-1 l−1 的节点能得到的与 s [ n ] ⊕ x s[n] \oplus x s[n]⊕x 异或最大的值
J - 病毒
题意
二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。
题解
- 如果拿一个安全代码在自动机上跑一定会不停的跑而到不了单词的结束点,这就要求必须有个环。
- 而且这个环要求必须经过根节点,且不经过一些限制节点。
- 限制节点包括单词的结束节点,还有若一个点的fail指向的点是限制节点那么这个点也是限制节点。
K - 列队
题意
有 n n n 个学生,编号为 i i i 的学生有一个位置 a i a_i ai
有 m m m 个询问,每次询问编号在 [ l , r ] [l,r] [l,r] 区间内的学生跑到区间 [ k , k + r − l ] [k,k+r−l] [k,k+r−l] 中的位置花费的距离总和的最小值。
每个学生的初始位置互不相同,最终到达的位置也必须互不相同。
题解
学生跑到最终的位置时,他们的相对位置不改变至少是最优解之一
考虑注意维护学生的位置,显然通过维护区间内学生个数,我可以知道区间内学生需要移动到的对应位置
- 若对应区间右端点大于等于区间学生位置最大值,所有学生向右跑即可
- 若对应区间左端点小于等于区间学生位置最小值,所有学生向左跑
- 分别对左右区间递归
显然我们只要维护区间内学生个数和学生位置权值和,就可以维护所有学生向左\右跑到对应位置的贡献
L - 情报传递
题意
查询树上路径长度和路径上权值小于 x x x 的点的个数
题解
-
设这是第 x x x 个任务,若 o p t opt opt 为 1,危险值大于 x x x 的只有可能在第$ x-c-1$ 个任务以前出现。
于是题目就变成了在某一时刻单点加和在某一时刻链上查询,离线即可去掉“某一时刻”。
-
树上路径长度,我们可以通过 L C A LCA LCA,路径长度为 d [ u ] + d [ v ] − 2 ∗ d [ l c a ] d[u]+d[v]-2*d[lca] d[u]+d[v]−2∗d[lca]
-
树上维护的小于等于 k k k 的树,我们可以使用主席树
定义 s [ u ] s[u] s[u] 从根节点到第 u u u 号节点的“前缀主席树”。那么,包含 u u u 到 v v v 上所有数值信息的主席树就应该是: s [ u ] + s [ v ] − s [ l c a ( u , c ) ] − s [ f a [ l c a ( u , v ) ] ] s[u]+s[v]-s[lca(u,c)]-s[fa[lca(u,v)]] s[u]+s[v]−s[lca(u,c)]−s[fa[lca(u,v)]]
M - Searching the String
题意
多组数据,每组给出一个文本和 n 个模式,0 代表能重叠,1 代表不能重叠,求每个模版串在文本串中出现的次数
题解
第一类,可重叠:与往常无异。
第二类,不可重叠:因为不可重叠,所以在匹配的过程中,需要记录此单词上一次出现的位置,记为 l a s t last last,当前出现单词的位置为 i i i,单词长度为 l e n len len ,如果满足 i − l a s t > = l e n i-last>=len i−last>=len,即表明没有与上一次出现的重叠。
N - 背单词
题意
给你一些字符串,让你对其进行排列,使得按以下规则花费最少
(x为字符串在自行排定的序列中的位置,当前字符串为a)
1.如果 a a a 存在后缀且 a a a 的后缀在 a a a 之后,花费 + = n 2 +=n^2 +=n2
2.如果 a a a 不存在后缀则花费 + = x +=x +=x
3.设 y y y 为 a a a 之前离其最近的是 a a a 的后缀的字符串的位置, a a a 存在后缀且 a a a 的后缀在 a a a 之前,则花费 + = x − y +=x-y +=x−y
题解
三条规则,规则一显然是可以被避免且没有后两种优的,规则二可以看做规则三的特殊情况,简单起见,只考虑规则三即可
可以直接贪心设 s j s_j sj 为离 s i s_i si 最近的后缀字符串
定义 a i = i − j a_i = i-j ai=i−j
a n s = m i n ( ∑ a i ) ans=min(\sum a_i) ans=min(∑ai)
第一步我们建立一颗trie树
第二步我们发现一个字符串有可能有很多后缀,所以我们需要判重,优于字符串的后缀与字符串之间存在有向的关系,便建立一张有向图。 x − > y x->y x−>y 代表 x x x 是 y y y 的后缀
O - 普通平衡树
题意
平衡树模板题
题解
套个版就能过
详细解过长,附一种SPlay的题解
https://www.luogu.com.cn/blog/pks-LOVING/more-senior-data-structure-te-bie-qian-di-qian-tan-splay
P - 文艺平衡树
题意
平衡树翻转模板题
题解
套个版就能过
详细解过长,附一种SPlay的题解
https://www.luogu.com.cn/blog/pks-LOVING/splay-chu-li-ou-jian-cao-zuo-fan-zhuai-cao-zuo-reverse