7.8 D
题意:给定一个序列,求序列中所有区间的最大子段和之和
考虑分治。设分治中心为 (mid),对于左边的每个后缀,预处理出最大子段和和最大后缀和,右边同理。
考虑一组 (L,R),([L,mid]) 的最大子段和为 (A),最大后缀和为 (x), ([mid+1,r]) 的最大子段和为 (B),最大前缀和为 (y)。如果 (Ale B),且 (x+yge B) 即 (yge B-x),贡献为 (x+y)。若 (x+y<B) 即 (y<B-x),贡献为 (B)。(A>B) 时同理。
所以其实是一个二维偏序,(Ale B) 和 (A>B) 分别做一遍,用树状数组维护。时间复杂度 (O(nlog^2n))。
7.10 D
题意:给定一棵树,多组询问,每次保留编号在 ([l,r]) 内的点和边,求连通块数量。
把两边都有点的边称为有效边,连通块个数就是点数 (-) 有效边数。
考虑编号为 (i) 的边,两端点为 (a,b),需满足 (lle i,a,ble b) 即 (llemin{i,a,b}lemax{i,a,b}le r),转换成二维偏序,时间复杂度 (O(nlog n))。
7.11 D
题意:给定三个序列,求出每个区间在三个数列中的极差之积的和。
考虑枚举右端点 (r),维护每个左端点的答案。同时对每个序列维护上升和下降两个单调栈。以上升为例,弹出栈中的某一个下标为 (y) 的元素时,设栈中前一个元素为 (x),那么对于每个 (i~(x<ile y)),([i,r]) 的最大值会增加 (a[r]-a[y])。
问题变成了:维护三个数组 (A,B,C),区间加,区间求 (sum A_iB_iC_i)。线段树即可。时间复杂度 (O(nlog n))。
7.13 D
题意:给定一个序列,多次询问区间 ([l,r]) 中有多少个子区间满足其中不同数字个数为奇数。
将询问离线。记 (f(l,r)) 为 ([l,r]) 内不同数字个数的奇偶性((0) 或 (1)),若 (l>r) 则为 (0)。枚举右端点 (r),维护每个左端点 (l) 的 (f(l,r)),并维护 (sumlimits_{i=1}^rf(l,i))。记 (p_i) 为 (i) 前面最后一个 (a_i) 的下标,当右端点从 (r-1) 变成 (r) 时,所有左端点在 ([p_r+1,r]) 中的区间的 (f) 都会异或 (1)。
使用线段树维护。每个节点维护 (sum) 表示 (sumlimits_{i=1}^rf(l,i)) 之和,以及三个标记:(t0) 表示 (sum) 加上了区间内 (0) 的个数,(t1) 表示 (sum) 加上了区间内 (1) 的个数,(rev) 表示是否 (0/1) 翻转。类似区间加乘,我们规定先 (t0/t1) 再 (rev)。给区间打上 (t0) 标记时,如果已经有 (rev),则改为打上 (t1) 标记,反之同理。
移动右端点时需要区间 (0/1) 翻转,区间打上 (t1) 标记。时间复杂度 (O(nlog n))。
7.15 D
(nle 1000) 时显然可以费用流。(nle 10^6) 时就要用队列优化贪心。
对于第 (i) 天,从第 (j) 天买 (x) 单位水的费用是 (x[m(i-j)+p_j])。考虑存在 (j,k~(j<k)),如果 (p_j-mjge p_k-mk),我们一定不会选择从第 (j) 天买水,因为一定可以从第 (k) 天买代替,并且不劣。
于是可以维护一个 (p_j-mj) 单调上升的队列,并维护该天的可用容量,初始为 (V)。每次比较队首和 (p_i) 哪个更优,如果队首优则从队首买,买空了则弹出队首,继续贪心。如果从队首买了 (x) 单位水,由于要运往第 (i) 天,队列中所有元素的可用容量都会减少 (x)。所以还需要维护一个全局 (tag)。
时间复杂度 (O(n))。
P5278 算术天才⑨与等差数列
考虑 (k eq 0) 时,区间 ([l,r]) 成为公差为 (k) 的等差数列的条件:
- 区间 (max-min=k(r-l))
- (gcdlimits_{l<ile r}(mid a_i-a_{i-1}mid)=k)
- 区间内数字互不相同
对于 1 和 2,直接用线段树维护。对于 3,求出 (p_i) 为 (i) 前面最后一个 (a_i) 的下标,问题转化成判断 (min{p_i}<l) 是否成立。也用线段树维护。修改时需要用 set
,可能会有亿些细节。
时间复杂度 (O(nlog n))。
P4216 [SCOI2015]情报传递
对于一次时间为 (t) 的询问,将时间小于 (t-c) 的点加 (1),问题转化成链上求和。
所以可以将询问离线,按 (t-c) 排序,单点加链上求和,转化成子树加单点求和,用树状数组 + dfs 序实现。
时间复杂度 (O(nlog n))。
CF765F Souvenirs
考虑枚举 (i),求出所有有用的二元组 ((i,j))。如果 ((i,j)) 是有用的二元组,且 (a_i<a_j),对于 (k~(j<k)),若 (a_j<a_k),则 ((i,k)) 一定是没用的。若 (a_k-a_ige a_j-a_k) 即 (a_kgedfrac{a_i+a_j}{2}),((i,k)) 也是没用的。因为对于一个区间,若其包含了 ((i,k)),则必定包含 ((j,k)),而 ((j,k)) 更优。
(a_i>a_j) 时同理。容易证明有用的二元组个数是 (O(nlog n)) 的。用主席树求出这些二元组后,问题转化成求 (lle a,ble r) 的二元组中差的绝对值的最小值。离线 + 树状数组即可。
时间复杂度 (O(nlog^2n))。
P7447 [Ynoi2007] rgxsxrs
将值域按照倍增的方式分成 (O(log V)) 个块:([1,15],[16,255],[256,4095],dots)
对每一个值域块用一棵线段树,维护原序列的和、最值,并只保留值在这个值域块内的数。
修改操作:对于每个值域块,在线段树上 暴力修改。走到线段树的某一个节点时,如果出现以下情况:
- 区间内没有数,直接返回
- (maxle x),没有数需要修改,直接返回
- (min-xge L),直接打一个区间减的标记。
否则继续往两边递归。到叶子节点时,如果这个位置的数 (-x< L),说明它要掉到(小于当前块)的值域块中,把它放到一个栈中,并在当前节点做一些修改。
然后,对于栈中的每一个元素,计算出它要去的块。在这棵线段树上,先递归到这个位置,把沿途所有标记都下传。然后再修改这个位置上的值。
查询就很好搞了。
时间复杂度分析:考虑对于每个数,暴力修改到这个位置,当且仅当它下落了至少一个块,而一个数最多下落 (log V) 次。所以修改的复杂度是 (O(nlog nlog V))。查询也是 (O(nlog nlog V))。
GYM Beautiful Sequence Unraveling
题意:定义一个长度为 (n) 数列是美丽的,当且仅当不存在 (i~(1le i<n)) 使得 (max{a_1,a_2,dots,a_i}=min{a_{i+1},a_{i+2},dots,a_n})。求长度为 (n) 且由数字 (1..k) 组成的美丽的序列个数。(nle 500,kle10^8)
发现这个 (k) 是吓唬人的,只需要求出用 (1,2,dots n) 种再组合一下就行了。
记 (f_{i,j}) 为长度为 (i) 且用了数字 (1..j) 的美丽的序列(不一定全用)。它等于 (j^i) 减去不美丽的序列数量。
枚举 (t) 表示最右边的满足 (max{a_1,a_2,dots,a_t}=min{a_{t+1},a_{t+2},dots,a_i}) 的位置。再枚举 (m) 表示 ([1,t]) 的 (max)。由于 (t) 是最右边的位置,([t+1,i]) 一定是一个美丽序列。而左边可以任意,只要最大值为 (m) 即可。
(f_{i,j}=j^i-sumlimits_{t=1}^{i-1}sum limits_{m=1}^j(m^t-(m-1)^t)(dp_{i-t,j-m+1}-dp_{i-t,j-m}))
但这是 (O(n^4)) 的,考虑前缀和优化。记 (g_{j,m}=sumlimits_idfrac{f_{i,j}}{m^i})
则 (f_{i,j}=j^i-sumlimits_{m=1}^jm^i(g_{j-m+1,m}-g_{j-m,m})-(m-1)^i(g_{j-m+1,m-1}-g_{j-m,m-1}))
再记 (h_j) 为:长度为 (n) 的,且 恰好用了 (j) 种数字的美丽序列数量。显然有 (h_1=f_{n,1})。
考虑将 ([1,x]) 内的数字重新标号成 ([1,y]) 内的数字(不改变相对大小),有 (C_y^x) 种方案。
则 (h_j=f_{n,j}-sumlimits_{k=1}^{j-1}h_kC_j^k)
答案为 (sumlimits_{j=1}^nh_jC_k^j)
而 (C_k^j=dfrac{k!}{(k-j)!j!}=dfrac{k!(k-j+1)}{(k-j+1)!(j-1)!j}=dfrac{k-j+1}{j-1}C_k^{j-1},~C_k^1=k),所以可以边推组合数边加答案。
时间复杂度 (O(n^3))。