题单

题意

link

给定序列 aa,并且给出两种操作:

  • 1 x y v:将所有 aia_i 的值加上 vv,其中 iy(mod2x)i\equiv y\pmod {2^x}
  • 2 x y:询问所有 aia_i 的和,其中 iy(mod2x)i\equiv y\pmod {2^ x}

题解

一道结合了 Trie 和 Lazytag 的好题。

我们考虑修改和查询涉及到的下标。

发现,一个数对 2x2^x 取模,就相当于取这个数的二进制表示的右 xx 位。于是,所有的满足 iy(mod2x)i \equiv y\pmod {2^x}ii 都有一个长度为 xx 的后缀 yy

所以,我们考虑把所有的下标的二进制形式倒序插入一颗 01-Trie,那么每次修改就是子树加,查询就是子树查询。

在 01-Trie 中维护 sumsumsizsiz 即可。

题意

link

给定 nn 天的气温 TiT_i,设第 ii 天温度为 PP,则第 i+1i+1 天的温度为:

  • P+1 (P<Ti)P + 1 \ (P < T_i)

  • P1 (P>Ti)P - 1 \ (P > T_i)

  • P (P=Ti)P \ (P = T_i)

对第 ii 天有 kik_i 个询问,问若第 00 天的温度为 xx,那么第 ii 天的温度是多少。

强制在线。

题解

比较小清新的数据结构。

考虑直接用一棵动态开点线段树维护初始温度在 [l,r][l, r] 之间的答案最小值和最大值。

再考虑增加气温时该如何维护。

当我们在 uu 节点时:

  • maxu<ti\max_u < t_i 这时可以直接将 uu 区间加 11

  • minu>ti\min_u > t_i 这时可以直接将 uu 区间减 11

  • minu=ti=maxu\min_u = t_i = \max_u 这时可以直接返回。

  • 否则,递归进入两棵子树。

时间复杂度为 O(nlogm)O(n \log m)

题意

link

给一个长度为 nn 的序列 aa,有 qq 次询问,每次询问一个区间内任意一个出现 11 次的数,如果没有,输出 1-1

题解

比较小清新的数据结构。

首先考虑限制条件的本质。

设数组 preipre_i 为使得 j<ij < iaj=aia_j = a_i 的最大的 jj,且当前左右端点分别为 l,rl, r,那么一个数 aia_i[l,r][l, r] 中只出现了一次当且仅当:

  • 它是 [1,r][1, r] 中最后一个 aia_i

  • prei<lpre_i < l

那么,在 [l,r][l, r] 中寻找的 aia_i[1,r][1, r] 中最后一次出现的,且 preipre_i 最小的 ii,如果这个 ii 不是解,必定没有解;否则输出 aia_i 即可。

维护在 [1,r][1, r] 中最后一次出现且 preipre_i 最小的 ii 可以用线段树,但是 rr 不固定,怎么办?有两种解决方案:

  1. 主席树。
  2. 将询问离线下来按照 rr 排序,只需要普通的线段树。

时间复杂度为 O(nlogn)O(n \log n)莫队垃圾

题意

link

给出一个 11nn 的排列,现在对这个排列进行 mm 次局部排序,排序分为两种,将区间 [l,r][l, r] 的数字升序或降序排序。

最后询问位置 pp 上的值。

题解

神仙二分 + 线段树。

我们考虑二分位置 pp 的值。怎么 check 呢?

我们考虑 check apxa_p \ge x

构造一个 01 序列 bbi[1,n],bi=[aix]\forall i \in [1, n], b_i = [a_i \ge x]

然后在 01 序列 bb 上执行排序操作,最后如果 bp=1b_p = 1apxa_p \ge x

为什么这样是对的呢?因为在 bb 序列中,元素的相对大小顺序没有改变,大于等于 xx 的元素还是大于小于 xx 的元素。

排序操作可以用支持区间修改的线段树实现。

题意

link

给定 nn 件物品,第 ii 件物品有如下信息:

  • 卖出去可以得到 pip_i 的收益。

  • 过期时间为 did_i,过了过期时间就不能再卖出去。

卖掉一件物品要用 11 的时间,求最大收益。

题解

首先,我们可以想到一个贪心思路:把物品按照 pip_i 从大到小排序,优先卖出 pip_i 大的物品,且每一个物品的卖出时间都尽量靠后。

所以对于每一个位置,我们支持占用一个位置,和求出某个位置前面第一个空闲的位置。

我们考虑使用并查集维护。如果占用了位置 pp,那么把位置 pp 合并到位置 p1p - 1 上,查询时查询某个位置的根节点。

时间复杂度为 O(nlogn)O(n \log n)

题意

link

给一个长度为 nn 的字符串,mm 次询问,每次询问一个连续子串是否可以重排成一个回文串。

题解

一道很不错的莫队题。

显然,一个区间重排后可以成为一个回文串当且仅当其中有 0011 个字符出现了奇数次。

我们只关心字符出现次数的奇偶性,所以我们可以把字符串所有的前缀状压成一个数,查询时直接异或即可。

添加 / 删除时枚举是哪一种字符出现了奇数次,时间复杂度为 O(Σnn)O(|\Sigma|n \sqrt n)

题意

link

给一个长度为 nn 的序列 aamm 次询问,每次询问区间众数。强制在线。

题解

首先可以把序列离散化。

然后发现答案只可能是在两个散块里的数,或者是整块段的众数。

整块段的众数可以 O(n)O(n) 预处理,两个散块里的数最多是块长级别,预处理出每一种数出现的位置,在位置数组里二分查找即可解决散块的问题,可以做到单次查询 O(blogn)O(b \log n)

经过亲测块长设 4040 比较优。

题意

link1

给你一个长度为 nn 的序列 aamm 次询问,每次询问一个区间是否可以选出两个数它们的和 / 差 / 积为 xx

选出的这两个数可以是同一个位置的数。

link2

在上一题的基础上,每次询问一个区间是否可以选出两个数它们的商为 xx

题解

ww 为值域,使用两个 bitset 分别统计 xxwxw - x 有没有出现过,使用 <<>> 操作即可统计加和减操作。

而乘操作可以暴力枚举质因子,时间复杂度为 O(nw64+nw)O(\frac{nw}{64} + n \sqrt w)

对于除操作,我们考虑根号分治。

如果 xwx \ge \sqrt{w},可以直接枚举 ii,判断 xxixix 是否同时出现。

否则对于每一个 xx 计算答案,求出 lasilas_iiiaa 中最后出现的位置,resires_i 为满足在 [l,i][l, i] 中同时出现 yyxyxyyyyx\frac{y}{x} 的最大的 ll。每一个询问检查是否满足 resrlres_r \le l 即可。设 ww 为值域,时间复杂度仍为 O(nw64+nw)O(\frac{nw}{64} + n \sqrt w)

题意

link

给一个长度为 nn 的序列,mm 次询问,每次查询一个区间 [l,r][l,r] 中所有子序列分别去重后的和 modp\bmod p。(pp 在每个询问里不同)

题解

考虑计算每一个数的贡献。假设区间长度为 ll,这个数在区间里出现了 tt 次,根据容斥原理(出现的次数减去不出现的次数),这个数的贡献就是 2l2lt2^l - 2^{l - t}

根据乘法分配律,相同的数可以一起乘,又因为同一区间内最多只有 n\sqrt n 种贡献,所以可以用一个双向链表来维护贡献为某个值的和,暴力计算。2k2^k 用光速幂处理一下即可。

题意

link

给你一个长度为 nn 的序列 aa

回答 qq 个这样的询问:aa 的左端点在 [l1,r1][l_1, r_1] 之间,右端点在 [l2,r2][l_2, r_2] 之间的子区间的中位数的最大值。

保证 l1<r1<l2<r2l_1 < r_1 < l_2 < r_2强制在线。

题解

对于求中位数,有一个套路:二分中位数 midmid,把所有 mid\ge mid 的值设为 11<mid< mid 的值设为 1-1,如果区间和 0\ge 0,那么 midmid 就可能成为区间里的中位数。

我们可以对于二分的每一个 aa 里的值开一棵对应的线段树,但是一棵线段树可以由之前的线段树修改而来,所以只需要一棵可持久化线段树即可。

但是区间不固定,所以我们应该尽可能让上式的值最大。容易发现,[r1+1,l21][r_1 + 1, l_2 - 1] 是必选,而 [l1,r1][l_1, r_1][l2,r2][l_2, r_2] 分别取最大前缀和与最大后缀和,套用小白逛公园的做法即可。

题意

link

定义一个可重集的神秘数为最小的不能被这个集合的子集和表示的数。

给一个长度为 nn正整数序列 aamm 次询问,每次询问由 al,al+1,,ara_l,a_{l+1},\cdots,a_r 所组成的可重集合的神秘数。

题解

我们先思考暴力做法:设当前覆盖区间为 [1,x][1, x],那么每一个 x+1\le x + 1 的项都对答案有贡献,设它们的总和为 sumsumansans+sumans \to ans + sum;如果没有这样的项,x+1x + 1 就无法被组成,答案为 x+1x + 1

每一次查找可以用可持久化值域线段树优化至 logw\log w,而每一次增长后 ansans 至少翻倍,最多只能增长 logai\log \sum a_i 次,所以时间复杂度为 O(nlognlogai)O(n \log n \log \sum a_i)

题意

link

你需要维护一个长度为 nn 的 01 序列。

你会接到 qq 条信息:

  1. 告诉你一个区间的按位或值。
  2. 问你序列中一个数的值。如果不能确定,输出 N/A

保证信息正确。

题解

我们称按位或为 xx 的区间为“xx 区间”。

可以发现一些性质:00 区间里每个数都是 0011 区间至少有一个数为 11

能确定一个数为 00,当且仅当一个 00 区间包含这个数;能确定一个数为 11,当且仅当一个 11 区间包含这个数,且该区间内其余的数均被确定为 00。所以,一个 11 区间至多能确定一个数为 11

我们考虑把操作序列离线下来,这样我们就可以算出每个位置得知所有信息后的值。然后求出每个位置能确定的最早时间即可。

具体来讲,我们记录所有修改操作和询问操作的时间,然后确定每个数最早被确定为 00 的时间。

然后对于每个 11 区间,如果该区间内有 >1> 1 个数到最后也未被确定为 00,则不考虑该区间;否则,设唯一的最后也未被确定为 00 的数在位置 pp,该区间内最后一个被确定为 00 的数在时刻 lstlst 被确定为 00,收到该区间的时刻为 tt,那么位置 ppmax(lst,t)\max(lst, t) 时刻可以被该区间确定为 11,一个位置能被确定为 11 的时刻显然是最先确定该位置的 11 区间确定该位置的时刻。

所有任务都可以用一棵线段树完成,时间复杂度为 O(nlogn)O(n \log n)

题意

link

有一棵无根树,点数为 nn,每个点有个点权 aua_u,定义一棵树是合法的,当且仅当树上所有简单路径上点权的异或和都不为 00

你可以对点权进行修改,可以改成任意正整数,问最少修改多少次才能让这棵树合法。

题解

启发式合并。

首先,对于每一个 uu,我们可以预处理出 11uu 的简单路径上点权的异或和,记为 dud_u。然后 uuvv 的简单路径上点权的异或和显然就是 dudvalca(u,v)d_u \oplus d_v \oplus a_{\operatorname{lca}(u, v)},我们考虑枚举 lca(u,v)\operatorname{lca}(u, v) 来修改 alca(u,v)a_{\operatorname{lca}(u, v)}

我们还发现,一个节点如果要修改的话,一定会改成远大于值域的一个极大值,使经过这个点的每一条简单路径的异或和都不为 00

所以我们考虑这样的一个贪心:对于每一个节点开一个 set 维护以这个节点为根的子树里所有节点 uudud_u,特别的,如果这个节点修改成了极大值,这个节点对应的 set 为空。然后对于整棵树 dfs 一遍,假设当前在节点 uu,递归进入每一个儿子 vv,回溯时将 vvset 使用启发式合并动态并入 uuset,并在插入过程中动态查找当前 uuset 中是否有两个数异或值为 aua_u。如果有,aua_u 必须修改成极大值,将 set 清空即可。至于清空的原因,是因为 uu 的子树里任何一个点都不可能与外面一个点构成一条异或和为 00 的简单路径。

贪心正确性显然,时间复杂度为 O(nlog2n)O(n \log^2 n)