(Day1)
报到日 , 无训练。
(Day2)
训练得分 (100 + 100 + 0 = 200)。
(A.)
将每个函数映射成一个数 , 可以通过 (std::map) 来实现。
转化后的问题相当于 (DAG) 路径计数。 时间复杂度 : (O(N))
(B.)
容斥原理。
首先预处理每个点的概率 , 然后对于每组和整体分别容斥即可。 时间复杂度 : (O(N ^ 2))
(C.)
设定阈值跑最短路。
时间复杂度 : (O(NB))
(Day3)
训练得分 (80 + 50 + 50 = 180)。
(A.)
首先在原树的基础上建出一棵新树 , 新树上每个点连向原树上恰好权值大于它的 , 最近的祖先节点。 可以通过倍增得到。
对于 (Q) 个询问 , 先在新树上倍增找到第一个权值比 (C) 大的节点。 然后继续倍增向上跳到第一个深度比 (U) 小的节点即可。
时间复杂度 : (O(NlogN))
(B.)
首先可以证明最小的环是三元环。 这是因为如果 (n(n geq 4)) 元环存在 , 则一定存在 ((n - 1)) 元环。 否则就没有环存在。
问题转化为了竞赛图上的三元环计数。 有一个经典的容斥原理做法 ,假设边集已经确定, 那么 :
(ANS = {n choose 3} - sum{deg_{u} choose 2})。
可以画图理解。
那么根据期望的线性性 , 就只需对每个点维护其已确定的出边和不确定的出边即可。
时间复杂度 : (O(N))
(C.)
首先考虑 , ({a_{i} + b_{i} + a_{j} + b_{j} choose a_{i} + b_{i}}) 这个式子等价于从 ((-a_{i} , -b{i})) , 每次向右或向上 , 到达 ((a_{j} , b_{j})) 的方案数。 可以根据组合意义来理解。 根据这个结论 , 直接求解 (NE Lattice Path) , 可以得到 (50) 分。
考虑从第四象限到第一象限的一条路径 , 我们发现其一定经过 (y = -x) 这条直线。 那么不妨对于直线上每个点维护方案数。 由于 (sum{a_{i}} + sum{b_{i}}) 不超过 (2 * 10 ^ 6) , 因此总的加点更新次数也不超过这个值。
时间复杂度 : (O(sum{a_{i}} + sum{b_{i}}))
晚上做了一下 (CEOI) 的两道题。
(The Potion of Great Power.)
用平衡树维护每对关系的出现时间。
对时间轴建立 (N) 棵线段树 , 我们只需将平衡树上的点加入线段树就可以维护出每个人在任意时刻的所有 "朋友"。
由于每个人每个时刻最多有 (500) 个朋友 , 因此只需在线段树上查询根到其的路径 , 得到它的朋友的 (h_{i})值。
然后 (Two-Pointers) 扫描 ,即可。时间复杂度 : (O(ND))
(Spring Cleaning)
首先有一个结论 , 对于 (size) 值为奇数的节点需要被覆盖一次 , 偶数的要覆盖两次。
这是为什么呢? 可以考虑直接构造 , 对于 (size) 为偶数的节点, 将其子树向上的链两两配对留下一组。否则将这些链两两配对最后留下 (1) 条链。
显然这样是最优的。
那么只需树链剖分 + 线段树维护即可。 也可以建出虚树进行树形 (DP) 以获得更优的复杂度。
时间复杂度 : (O(QlogN))
(Day4)
训练得分 (100 + 40 + 29 = 169)。
(A.)
因为是一棵树 , 所以对于每个询问 ,
(联通块数量 = (R - L + 1) - 两个端点都在[L , R]区间内的边数)。
二维数点即可 , 可以离线后用树状数组统计。
时间复杂度 : (O(QlogN))
(B)
首先考虑一个容斥原理的做法 , 对行列容斥 , 枚举容斥了 (i) 行和 (j) 列 , 那么相当于将这 (i) 行和 (j) 列的限制减去了 (1)。可以得到 (10) 分。
注意到每个位置的取值之和其行和列的最小值有关 , 它们互相独立。
因此枚举行和列中小的值 , 进行上述的容斥原理。 通过乘法原理把容斥得到的值乘起来即可。
时间复杂度 : (O(N ^ 3logN))
(C)
提交答案题。
前 (6) 个点高精度算 (2)的次幂。
后面的点可能需要用到 (Method of four Russians) ?
下午做了两个题 :
(Calc)
来自于 (2012) 年的国家集训队互测。
首先我们设 (f(n , A)) 表示前 (n) 个数构成递增序列 , 其中第 (n) 个数的值不超过 (A) 的序列乘积和。 这是无序的情况 , 那么有序的情况答案就是 (f(n , A) * n!)
有转移方程 : (f(n , A) = f(n , A - 1) + f(n - 1 , A - 1) * A)。 这是通过枚举第 (n) 个数得到的。
注意到 (n) 很小 , 但是 (A) 很大 , 不难想到插值。
引理 : (f(n)) 的每个位置的取值是一个 (2n) 次多项式的点值。
证明 : 将转移方程移项得到 : (f(n , A) - f(n , A - 1) = f(n - 1 , A - 1) * A)。 我们知道对于一个 (n) 次多项式 (P(x)) , 有 (P(x) - P(x - 1)) 是关于 (x) 的 ((n - 1)) 次多项式。 所以 如果设 (f(n)) 的次数为 (g(n)) , 就有 (g(n) - 1 = g(n - 1) + 1) , 而显然又有 (g(0) = 0) , 因此 (g) 是公差为 (2) 的等差数列。
因此只要求出 (f(n , Delta)) , 其中 (Delta leq 2n) , 然后通过拉格朗日插值求出答案。 插值公式和定理就不赘述了。
时间复杂度 : (O(N ^ 2))
(LOJ2977)
来自于清华集训 (2017) 。
我们注意到如果颜色数量不大那么显然是可以求最小斯坦纳树的。
对于颜色数量很大的情况 , 我们将每种颜色随机映射为 ([0 , K]) 中的一个整数。 再求解斯坦纳树问题。 这样一次随机的正确率是 (K! over K ^ K)。
执行上述过程 (150) 次以上 ,答案的正确率超过 (99.99\%) ,那么就可以顺利通过这道题了。
时间复杂度 : (O(NM * 2 ^ K))
(Day5)
训练得分 (87 + 91 + 0 = 178)。
(A.)
发现如果 (t) 时刻成立 , 那么在 ((t + 1))时刻也必然成立。
这是为什么呢? 假设 (t) 时刻选出的函数的 (k) 值和比 (0) 大 , 那么 ((t + 1)) 时刻显然也是成立的。 否则 (0) 时刻显然也是满足的 , 与 (t) 时刻是最小满足的点矛盾。
因此虽然不满足单调性 , 但是是可二分的。
因此首先判断 (0) 时刻是否可行 , 再进行二分求解即可。 注意二分中的排序我们并不需要用快速排序算法 , 只需要用(GNU C++)自带的 (std :: nth underline{} element) 函数即可。
时间复杂度 : (O(NlogN))
(B.)
首先可以将每个点用 (x_{1}) 表示出来 , 形如 (x_{i} = k_{i} * x_{1} + w_{i}) 其中 (k in {-1,1})。
(k_{i}) 的符号和节点在树中的深度有关 , 而对于修改操作 , 又可以看做对子树中深度为奇数 / 偶数的节点的 (w) 值做加法 / 减法。可以通过 (DFS) 序 + 树状数组 的方式求得。
对于每个询问 , 根据节点奇偶性讨论解方程即可。 细节较为繁琐 , 需要精细实现。
时间复杂度 : (O(MlogN)) , 需要注意常数优化 ,因为输入量较大 , 可以使用 (mathbb{fread}) 读入。
(C.)
首先枚举矩形横向的 (L) 和 (R)。
对这两条线进行扫描线 , 枚举两条线中最靠下的那个点 ,计算其对答案的贡献即可。
可以用数据结构来优化这个过程。
细节很多 , 需要精细实现。
时间复杂度 : (O(NMlogN))
(Day6)
(AGC039F)
首先定义 (a_{i}) 为第 (i) 行最小的数 , (b_{j}) 为第 (j) 列最小的数。
算恰好等于是很复杂的 , 我们考虑至少的情况 , 那么
其权值为 (prod_{i=1}^nprod_{j=1}^m{a_{i}b_{j}}) , 方案数为 (prod_{i=1}^nprod_{j=1}^m{(D - max{a_{i} , b_{j}} + 1)})。
考虑容斥原理 , 我们容斥一行或一列 , 则相当于将其限制加上了 (1)。
考虑直接动态规划 , 令 (f_{i,j,k}) 表示使用了 ([1 , i]) 范围内的权值 , (j) 行 (k) 列的答案 , 那么每次就只需要枚举加入的行数 ,加入的被容斥的行数 , 加入的列数 , 加入的被容斥的列数即可。
这样复杂度是不能接受的 , 但我们可以分 (4) 个阶段转移并预处理转移系数。
时间复杂度 : (O(N^3))
(AGC036C)
首先有一个结论 , 一个序列合法当且仅当其长度为 (N) , 最大值不超过 (2M) , 奇数的个数不超过(M)。
考虑证明 , 必要性显然 , 充分性可以构造证出。
忽略最大值的限制 , 定义 (F(N , M , K)) 表示 (N) 个数 , 和为 (M) , 奇数的个数不超过 (K) 的方案数。 只需用一些组合数的技巧 , 就可以在 (O(N)) 的时间内解出这个函数。
然后再考虑最大值 , 考虑容斥原理 , 用合法减去不合法 , 枚举最大的那个数 , 将其减去 (2M) (因为这样不会对奇偶性的限制造成影响)。
我们要求的是剩下的 (N) 个数和为 (M) , 奇数个数不超过 (M) ,且枚举的数比 (0) 大的方案数。
考虑再进行一次容斥原理 , 用 (F(N , M , M) - F(N - 1 , M , M)) , 就得到了上面要求的。
综上 ,答案为 (F(N , 2M , M) - N(F(N , M , M) - F(N - 1 , M , M)))。
预处理组合数即可 , 时间复杂度 : (O(N))。
(Day7 - Day13)
军训。
(Day14)
正睿十连测第三场 :
(A)
直接给出结论 , 当 (M = 0) 时不可能 , 否则一定有一种方案。
可以构造证明。
还有一种证明方法是求出期望的符合要求边数是 (M over 2) , 因此除了 (M = 0) 的情况 , 其它都一定有一组解。
时间复杂度 : (O(1))
(B)
首先我们发现操作是可逆的.
因此我们定义 (f(s)) 表示字符串 (s) 通过题目中描述的操作所能得到的 , 字典序最小的串。问题转化为是否有 (f(a) = f(b))。
注意 , 这里的"字典序" 是指在 (0) 的个数最多的情况下 , (1) 的位置尽可能靠前。
发现如果有连续的 (k) 个 (0) 后面跟着一个 (1) , 那么就可以用这个 (1) 和前面的第一个位置交换。
因此 , 直接用堆栈模拟这个过程 , 每次遇到 (k) 个连续的数就弹栈。
时间复杂度 : (O(N))
(C)
首先记"不属于"关系的集合为 (A) , "属于" 关系的集合为 (B)。
考虑集合 (B) , 将集合中的值排序后 , 公差显然为 (gcd(b_{1} - b_{0} , b_{2} - b_{1} , b_{3} - b_{2} , .... , b_{n} - b_{n - 1})) 的约数。
不妨考虑枚举公差 , 对于每种差值 , 计算可能的序列有多少种。
于是考虑集合 (A) , 枚举其中的每一个元素 , 算出左右端点的取值范围即可。
时间复杂度 : (O(M sqrt{M}))
(CF1406E)
交互题。
首先线性筛 , 求出 (N) 以内的所有质数。
将质数分为 (sqrt{M}) 块。
枚举最小质因子 , 每次可以先将序列中最小质因子在块内的数去除 , 再通过询问 ("A 1") 来判断 (x) 是否有块内的因子。
最后我们枚举 (x) 的每个质因子 , 通过 (A) 类询问求出其次幂 , 再将这些值相乘 , 即可。
总操作数 (M + 2sqrt{M} + log(M))
代码 : https://codeforces.ml/contest/1406/submission/92755571
(AGC035F)
首先设 (a_{i}) 表示第 (i) 行染的长度 , (b_{j}) 表示第 (j) 列染的长度。
若 (a_{i} = j - 1 , b_{j} = i) , 那么令 (a_{i} = j , b_{j} = i - 1) 可以获得同样的效果。
结论 :
答案为不存在 (a_{i} = j - 1 , b_{j} = i) 这样情况的方案数。
证明 :
我们设两个不同的染色方案 (a , b , a' , b') 的作用相同。
找到最小的 (b_{j}
eq b_{j}') , 令 (b_{j} < b_{j}') , 并记 (r = b_{j})。
因为两个网格同构 , 所以有 (a_{r} geq j , a_{r}' < j)。
若 (j = 1) , 则 (a_{r}' = 0) , 矛盾。
若 (j > 1) , 则 (a_{r}' < j - 1) , 而 (a_{r} geq j , b_{j} = b_{j - 1}) , ((r , j - 1)) 位置在两种方案下取值不同 , 矛盾。
有了这个结论后 , 就可以进行容斥原理 / 二项式反演了 , 答案为 :
(sum{ {n choose i}{m choose i}i!(m+1)^{(n-i)}(n+1)^{(m-i)} })。
预处理阶乘 ,阶乘逆元 , ((n + 1) , (m + 1)) 的幂次即可。
时间复杂度 : (O(NlogN))。
代码 : https://atcoder.jp/contests/agc035/submissions/16747257
(Day15)
训练得分 : (100 + 80 + 100 = 280)。
(A)
令 (dp_{i}) 表示前 (i) 个 , 最小代价是多少。
(dp_{i} = min(dp_{j - 1} + K + S(mx - mn)))。
时间复杂度 : (O(NM))。
(B)
首先建出最短路径生成树。
每次删除一条边 , 运行 (BFS / DFS) , 将生成树上影响到的节点删除即可。
时间复杂度 : (O(N + M))
(C)
首先枚举对角线。
然后枚举右下角 , 计算左上角对其的贡献。
用扫描线 (+) 树状数组统计即可。
时间复杂度 : (O(NMlogN))。
(AGC007E)
首先二分答案 (mid)。
设 (dp_{u , l , r}) 表示以 (u) 为根的子树 , 第一次走到了叶子节点 (l) , 最后一次走到叶子节点 (r) , 每次经过边权不超过 (mid) , 是否可行。
这个动态规划该如何转移? 显然可以直接考虑左边和右边 , 两两合并即可。
这样做是 (O(N ^ 3logN)) 的。
考虑优化 , 首先观察到一个性质 :
如果有两个可行状态 (dp_{u,l1,r1}) 和 (dp_{u,l2,r2}) , 满足 (l1 leq l2 , r1 leq r2) , 那么后者是无用的。
这个结论显然正确。
因此将可行的状态按 (l) 排序 , 右端点必然单调递减。
这样我们就可以枚举一个子树的 (l) , 在另一棵子树中 , 找到左端点最大的与其匹配即可。 可以用 (Two-Pointers) 优化。
然后注意到另一个性质 : 一个子树 (S) 的可行状态数是 (2|S|) 级别。
用类似启发式合并的复杂度分析可以证明 , 这个做法的时间复杂度是 (O(Nlog^2N))。
(Day16)
训练得分 : (100 + 100 + 100 = 300)。
(A)
不难证明能往后放就尽可能往后一定是最优的。
预处理前 (20) 个菲波那契数 , 哈希 / 平衡树求解。
时间复杂度 : (O(NlogN))。
(B)
将字符串 (A) 中每个字母映射到 (B) 中去。 树状数组 / 归并排序求逆序对数即可。
时间复杂度 : (O(NlogN))
(C)
首先简化题意。 将圆上问题转化为序列上的问题。
每个操作相当于给数轴上一段区间插入一个数。 那么相当于在 (l) 处插入一个数 , 在 (r) 处删除这个数。
对于每一个划分段分别统计答案 , 我们要求的是覆盖它的数(圆)中半径第 (K) 大的。
在树状数组上二分即可 , 还有一种做法是用堆来实现 , 当堆的大小小于 (K) 时 , 将前面一段的答案一起计算。
时间复杂度 : (O(NlogN))。
(Day17)
训练得分 : (0 + 0 + 60 = 60)。
(A)
结论 (1) : 一个"好" 数必然是另一个 “好” 数乘上一个质数。
结论 (2) :一个 (10 ^ {18}) 以内的"好"数的最大质因子不超过 (67)。
暴力搜索即可。 时间复杂度 : (O(KlogK))
(B)
考虑将两个数组分别从大到小排序。
对于每个请求 , 取出符合条件中最小的那个 , 并将 ((val - w)) 放入一个大根堆 , 如果没有 , 就使用一次修改。
最终取出堆中最大的 (K) 个值 , 将其减去。
时间复杂度 : (O(NlogN))。
(C)
我的做法 :
首先最优方案必然是一个子树中选取一个点 , 再在另外一部分中选一个点。
在这两个点的 (LCA) 上统计答案。 做树形 (DP) 即可。
按照题目中所述的生成方式 , 树高不超过 (logN) , 每个节点的子节点个数不超过 (ln N)。
固时间复杂度 : (O(Nlog^3N))。
标准做法 :
延续刚才的思路 , 枚举一条断边。 对于剩下的两部分分别求带权重心即可。
这个做法的时间复杂度 : (O(NlogN)) , 可以通过 (D = 100) 的数据。
(CF1053C)
首先考虑一个经典问题 :
(|a_{1} - x| + |a_{2} - x| + |a_{3} - x| + ..... + |a_{n} - x|) 的最小值是多少?(x为整数)
显然当 (x) 取 ({a}) 的中位数最优。
接着 , 考虑带上权值怎么做 , 即 :
(w_{1} cdot |a_{1} - x| + w_{2} cdot |a_{2} - x| + ..... + w_{n} cdot |a_{n} - x|) 的最小值。
那么 (x) 的值取 (sum_{i=1}^{x}{w_{i}}) 恰好大于等于 (sum_{i=x+1}^{n}{w_{i}}) 时最小、
这是因为如果 (x) 右移时式子的值会减小。
那么这个题怎么做呢?
将一段区间整体移动 , 相当于先移动到一个固定的点再调整 , 因此转化为了上述问题。
列出答案的式子 , 化简后发现只要知道 (sum{w_{i}}) 和 (sum{w_{i} - i}) 即可 , 可以使用两个支持单点修改区间查询的数据结构维护 , 那么树状数组不失为一个不错的选择。
时间复杂度 : (O(NlogN))。
(Day18)
训练得分 : (70 + 100 + 40 = 210)。
(A)
考虑当前一个数 (x) , 有四种转移 :
(1.) 花费 (1) 步 , 将这个数加一。
(2.) 花费 (1) 步 , 将这个数减一。
(3.) 花费 (4) 步将其复制 , 再用 (2k) 步将其乘 ((k + 1))。
(4.) 花费 (3) 步将其清零。
那么直接运行最短路即可。
用 (SPFA) 算法 + (SLF)优化可以获得比 (Dijkstra) 更优的复杂度。
时间复杂度 : (O(NlogN)) (存在很小的常数)
(B)
我的做法 :
建图二分图匹配。
时间复杂度 : (O(N ^ 2))。
(C)
首先观察到答案不超过 (2n) , 这是因为每次取最大的最多只需用 (2) 次操作就能换到其对应的位置。
因此迭代加深 + (DFS) 就可以得到 (40) 分。
接着 , 我们注意到每次交换后 , 最多只有一个 (|a_{i} - a_{i - 1}|) 的值发生改变。
因此可以将估价函数定义为 (|a_{i} - a_{i - 1}|) 不为 (1) 的个数。
(IDA*)即可 , 时间复杂度 : (O(?))
(CF1139F)
首先考虑题目中给出的条件 :
(p_{i} leq inc_{j} leq s_{i})
(|b_{i} - pref_{i}| leq (inc_{j} - p_{i}))
显然可以将绝对值展开 , 那么 , (i) 对 (j) 产生贡献当且仅当
1). (p_{i} leq inc_{j} leq s_{i})
2). (inc_{j} + pref_{j} geq b_{i} + p_{i})
3). (pref_{j} - inc_{j} leq b_{i} - p_{i})
考虑这三个条件的含义 , 将 (inc) 值作为横轴 , (pref) 值作为纵轴 , 发现 (i) 能够造成的贡献的点恰好为平面上的一个等腰三角形。如图(来自陈栉旷) :
考虑扫描线并进行差分 , 在扫描到 (b_{i}) 时加入这个三角形 , 在扫描到 (s_{i} + 1) 时去除这个三角形所造成的影响。
除此以外 , 还需要支持查询某个点在多少个三角形内。
于是考虑第 (i) 个三角形造成的影响 , 可以看成
1). 在直线 (x + y = b_{i} + p_{i}) 上贡献 (1)。
2). 在直线 (y - x = b_{i} - p_{i} + 1) 上贡献 (-1)。
询问相当于询问横坐标为 (inc_{j}) , 纵坐标不超过 (pref_{j}) 的贡献之和。
那么对于 (x + y) 和 (y - x) 分别维护一个树状数组即可。
时间复杂度 : (O(NlogN))。
(Day19)
(AGC022E)
考虑给定一个序列 , 判断其是否合法。
不妨维护一个栈。
如果加入的数是 (0) :
如果栈顶已经有两个 (0) , 将三个数 (0) 合并为一个 (0)。
否则加入这个 (0)。
如果加入的数是 (1) :
如果栈顶是 (0) , 那么删除这个 (0) , 因为这三个数的中位数取决于下一个数。
否则加入这个 (1)
那么就有一个动态规划的思路了 :
记 (dp_{i , j , k}) 表示前 (i) 个数 , 栈中有 (j) 个 (0) , (k) 个 (1) , 有多少种不同的序列。
(j) 和 (k) 不超过 (3) , 因此时间复杂度 : (O(N))。
事实上这个转移可以看做有限状态自动机 , 可以矩阵乘法做到 (O(logN)) 级别 , 不过放在这题没有必要了。
(AGC030F)
首先如果两个数都已经确定 , 那么显然可以去除。
那么剩下的数就是两个数中只有 (1) 个不确定的和两个都不确定的。 将只有一个数不确定的组中 , 不为零的那个数的 (v) 值标记为 (1)。
将 (1 - 2N) 顺次排成一排 , 配对的连一条线 , 那么 , (B) 中的元素就是每条线的左端点的值。
如果这条线两端的值都没有在 (A) 中,那么我们先不给这条线赋值,等到最后统计完所有方案后,可以发现这样的线的个数是确定的(就等于 (N) 减去一端在 (A) 中的数对的数量),假设为 (|S|) ,把答案乘以 (|S|!) 就行了。
两个方案不同当且仅当 :
1). 有一个点在第一个方案中是左端点 , 而在另一个方案中不是左端点。
2). 两个左端点所在的线的编号不同。
考虑从大到小动态规划 , 记 :
(dp_{i , j , k}) 表示大于等于 (i) 的数中 , 有 (j) 个 (v_{x} = 0) 的点没配对 , 有 (k) 个 (v_{x} = 1) 的点没配对。
时间复杂度 : (O(N ^ 3))
(CF1227F)
首先将 (A) 类区间和 (B) 类区间分别插入两棵不同的线段树。这两棵树的值域为 ([0 , 2 ^ {60}]) , 这样每个节点的长度都是二的次幂。
将输入区间拆成的次幂对应在线段树上的节点标记为黑色节点。
考虑两个节点的贡献 , 显然和深度较小的那个节点有关。
那么就有一个 (O(N^2L^2log(N^2L^2)))的思路了 :
枚举两棵树上的两个黑色节点 , 那么对一个形如 ([x , x + 2 ^ {d}]) 的区间造成了贡献 , 这也对应了一个线段树上的节点。
以线段树上 (DFS) 序从小到大的顺序枚举计算即可 , 具体而言 , 就是如果一个节点的祖先节点没被标记 , 就加上它的贡献。
然而这样是不能通过的。 需要发现一些其他性质 :
考虑两个节点 (p , q) , 其中 (dep_{p} < dep_{q}) , 那么将 (q) 变成它的父亲节点所造成的贡献是相同的。
因此可以换一种枚举方式 :
枚举两个节点 (p , q) , 其中 (dep_{p} = dep_{q}) , 并且(p) , (q)中有一个黑色节点。 计算这两个点形成的异或区间。
这样复杂度是 : (O(N ^ 2Llog(N^2L)))。
(LOJ2743)
一个经典问题 , 来自于(2016)年日本信息学竞赛((JOI))夏令营。
考虑将 (A) 从小到大排序 , 依次加入这个序列。
如图 , 在 (A_{i}) 不断增大的过程中 , 维护直线 (y = A_{i}) 下方的长度和。
于是定义 (DP) 状态 (f_{i , j , k , h}) , 表示插入了 (i) 个数 , 分成了 (j) 个联通块 , 当前的总和为 (k) , 选出了 (h) 个边界的方案数。
这样定义状态的好处是 , 只需保证两段之间有空位或是否在边界即可 , 而并不关心其实际位置。
不难发现 , 每次从 (f_{i}) 转移至 (f_{i + 1}) , 每段会增加 (A_{i + 1} - A_{i}) , 因此贡献为 ((2j - h)(A_{i + 1} - A_{i}))。
具体转移不再赘述了 , 需要分 (5) 类情况讨论。
时间复杂度 : (O(N ^ 2L)) , 可以使用滚动数组优化第一维空间。
(Day20)
整理山东省队集训题
(Day21)
训练得分 : (70 + 80 + 60 = 210)。
(A)
记 (dp_{S , i}) 表示当前队列里人的集合为 (S) , 有 (i) 个不满足关系的方案数。
时间复杂度 : (O(2^NN^2))。
(B)
对于每个右端点计算其贡献。
维护两个单调栈和支持区间赋值 , 询问区间和的最大 / 最小线段树。
时间复杂度 : (O(NlogN))
(C)
考虑期望的线性性 , 有 (E(A) = sum{E(A_{i})} = sumsum{E(A_{i} , A_{j})})。 其中 (E(A_{i} , A_{j})) 是 (A_{j}) 排在 (A_{i}) 之前的概率。
考虑一个 ([L_{i} , R_{i}]) 的贡献 , 是一个等差数列 + 一段区间加同一个数的形式。
那么维护一棵支持区间加法和区间加等差数列的线段树即可。
时间复杂度 : (O(NlogN))
(Day22)
训练得分 : (100 + 0 + 100 = 200)。
(A)
求 (AND) 的最大值 , 显然可以从高到低判断是否每一位能为 (1)。
求 (OR) 的最大值 , 可以用高维前缀和解决。
求 (XOR) 的最大值 , 可以用 (Trie) 树贪心。
时间复杂度 : (O(NlogM + 2 ^ M * M))
(B)
第一个性质 : 每个点无论如何运动 , 排名不变。
第二个性质 : 两个点相遇后反向运动 , 不考虑编号的情况下 , 等价于两个点按原来的方向继续行进。
对于每组询问二分答案求第 (K) 小排名的点即可。
时间复杂度 : (O(QlogN))。
(C)
每加一个数的贡献是 ((A_{i + 1} - A_{i}))。
设 (dp_{i , j , k}) 表示前 (i) 个数 , 当前和为 (j) , 分成 (k) 组的方案数。
分类讨论转移即可。
时间复杂度 : (O(N ^ 2K))。
(Day23)
训练得分 : (100 + 100 + 0 = 200)。
(A)
将小于 (b) 看成 (-1) , 将大于 (b) 看成 (1) , 一段数的中位数为 (b) 当且仅当这段的权值和为 (0)。
前缀和 + 哈希维护即可。
时间复杂度 : (O(NlogN))
(B)
建最短路图 , (Tarjan) 求割边即可。
时间复杂度 : (O(N + M))
(C)
搜索即可。
时间复杂度 : (O(?))。
(LOJ6039)
首先发现 (C_{i}) 很小 , 因此可以将 (C_{i}) 相同的合并。
对于一段 (C_{i}) 相同的 , 一定是取最大价值的优先考虑。
于是设 (f_{i , j}) 表示小于等于 (i) 的权值 , 用了容积 (j) , 获得的最大收益。
按照 (j) 模 (i) 的意义下分类 , 有 (f_{i , j} = max(f_{i - 1 , j},f_{i - 1 , j - ik} + V_{i , k}))。
注意到 (V) 值的斜率是单调不增的 , 因此该转移具有决策单调性。
那么分治优化决策单调性 (DP) 即可。
时间复杂度 : (O(NMlogN))
(LOJ6029)
线段树维护区间的 (Max) 和 (Min) 值 , 一次除法操作 , 如果区间的最大最小值变化量相同 , 那么相当于区间减操作。
定义一个区间的势能为 ((Max - Min)) , 这个区间的势能变化量不超过 (log) 次 , 故时间复杂度 : (O(Nlog^2N))。
(Day24) - (Day27)
/
(Day28)
训练得分 : (100 + 10 + 0 = 110)。
(A)
答案一定是相邻两个数最优。
线段树维护即可 , 时间复杂度 : (O(MlogN))
(B)
考虑一个非好数 , 将最大数加入这个数的左右两边 , 非好数数量不变。
动态规划即可。
时间复杂度 : (O(N ^ 2))
(C)
(S) 到 (T) 的路径异或和一定是 (S) 到 (T) 的任意一条路径异或若干个环的形式。
将环插入线性基 , 按位计算答案。
时间复杂度 : (O(MlogN))
(Day29)
训练得分 : (100 + 100 + 0 = 200)
(A)
基环树上的期望问题。
先拓扑排序 , 环上点的期望是一定的 , 先算出环上的期望 , 然后逆着拓扑序计算即可。
时间复杂度 : (O(N))
(B)
将曼哈顿距离转化为切比雪夫距离。
扫描线 + 线段树计算答案即可。
时间复杂度 : (O(NlogN))
(C)
不难发现题目中的条件为两点在同一个边 - 双连通分量中((e-DCC))。 也就是被至少一个环所包含。
首先建出最小生成树。
用并查集维护每个点向上第一条未被覆盖的边。
按边权从小到大枚举非树边 , 用并查集合并未被覆盖的边 , 在合并过程中建出一棵重构树 , 查询时求重构树上最近公共祖先即可。
时间复杂度 : (O((N + Q)logN))