List
Easy Problem
C
F
840
D
\color {blue} {CF840D}
CF840D
C
F
1422
D
\color {green} {CF1422D}
CF1422D
P
2048
\color {blue} {P2048}
P2048
P
5283
\color {purple} {P5283}
P5283
Good Problem
P
2303
\color {blue} {P2303}
P2303
P
4768
\color {blue} {P4768}
P4768
C
F
1416
D
\color {blue} {CF1416D}
CF1416D
P
5025
\color {purple} {P5025}
P5025
Tips
CF804D
考虑主席树。
每次询问执行主席树上扫描即可。假设本题询问的区间是 [ L , R ] [L,R] [L,R],当前扫到的值域区间 [ l , r ] [l,r] [l,r]。如果左子区间的数在 [ L , R ] [L,R] [L,R]中出现的次数之和超过了 R − L + 1 k \frac {R-L+1} k kR−L+1,那么搜索左区间,否则搜索右区间;如果都没超过直接返回。
考虑这么做的时间复杂度是多少。不难发现,对于主席树上的每一层至多只有 k k k个位置被扫描到并继续向下进行搜索;所以总时间复杂度是 O ( n k log n ) O(nk \log n) O(nklogn)的。
P2303
通过欧拉反演,不难得到答案为 s u m d ∣ n φ ( i ) n i sum_{d|n} \varphi(i) {\frac n i} sumd∣nφ(i)in。
直接枚举因数是 O ( n ) O(\sqrt n) O(n)的,但是单次计算欧拉函数的代价之和很高。并且这个式子不能使用杜教筛来优化。
参考一下根号分治的思想我们不难得到正解。我们通过线性筛求出所有不超过 l i m lim lim的数的 φ \varphi φ值。我们找到所有 n n n的约数 p i p_i pi,如果 p i p_i pi的值不超过 l i m lim lim直接调用,否则暴力在根号复杂度内计算 φ \varphi φ值。
当 l i m lim lim取到 n 0.72 n^{0.72} n0.72的时候可以通过。
CF1422D
考虑规划一条路径为“从一个闪现点到另一个闪现点”,不难发现两点 ( a , b ) ( c , d ) (a,b)(c,d) (a,b)(c,d)之间的路径距离为 m i n ( ∣ a − c ∣ , ∣ b − d ∣ ) min(|a-c|,|b-d|) min(∣a−c∣,∣b−d∣)。
但是,如果我们枚举所有的点对并连边的话时间复杂度,并跑最短路的时间复杂度为 O ( n 2 ) O(n^2) O(n2)。我们需要优化这个算法。
首先,我们对模型进行一步转化。两点 ( a , b ) ( c , d ) (a,b)(c,d) (a,b)(c,d)之间我们可以连两条边,边权分别是 ∣ a − c ∣ |a-c| ∣a−c∣和 ∣ b − d ∣ |b-d| ∣b−d∣,这样就将两点之间的边权式子给简化了。同时,我们发现,对于满足横坐标分别为 x 1 , x 2 , x 3 x_1,x_2,x_3 x1,x2,x3的 1 , 2 , 3 1,2,3 1,2,3号点, 1 1 1到 2 2 2的距离为 x 2 − x 1 x_2-x_1 x2−x1, 2 2 2到 3 3 3的距离为 x 3 − x 2 x_3-x_2 x3−x2,而 1 1 1到 3 3 3的距离是 1 1 1到 2 2 2的距离与 2 2 2到 3 3 3的距离之和!所以,我们根本不用连接 1 1 1与 3 3 3号点。扩展到多个点的情况,我们只需要将横坐标排序并将相邻两个点做连边操作,再对纵坐标排序并将相邻两个点做连边操作即可。
由于边数为 2 ( n − 1 ) 2(n-1) 2(n−1),点数为 n n n,所以跑最短路的复杂度是 O ( n log n ) O(n \log n) O(nlogn),可以通过。
P4786
NOI 2018 D1T1竟然是个裸题,NOI 2020 D1T1也是
首先,可爱的Yazid一定是开车到达某个节点 r t rt rt并下车之后步行到终点。
我们建出关于海拔的Kruskal重构树。注意建立的应该是最大生成树而非最小生成树。根据此时重构树的小根堆性质,此时两个点能够互相到达当且仅当它们的LCA的点权大于 p p p。
此时我们先考虑一个暴力做法: 在Kruskal重构树上枚举这个LCA,要求这个LCA的点权必须大于 p p p;对于所有满足要求的LCA,与 v v v异子树的叶节点的 d i s dis dis值的最小值即是答案。这里一个节点的 d i s dis dis表示它与 1 1 1号节点的最短路径长度。
考虑如何优化这个暴力。首先, d i s dis dis要用Dijkstra预处理出来 ① ^{①} ①。然后,我们处理出每一个子树内的所有叶节点的 d i s dis dis的最小值。对于每次询问,我们直接倍增即可求出答案。
时间复杂度为 O ( T × n log n ) O(T×n \log n) O(T×nlogn)。
①: 这句话是有深意的。这道题是OI历史上的一个里程碑——SPFA的死去。特加这一个注释,悼念已经离我们而去的SPFA算法。事实上,SPFA并没有完全死去,在Johnsen全源最短路、差分约束、负环判定以及一些极其难卡掉(如一些神奇的费用流建图题)或者数据完全随机的题目中有复杂度为线性,有重要的作用。
CF1416D
考虑给每条边一个边权,表示它在什么时候被删去。特别的,对于那些一直没有被删去的边,令它的权值为 q + 1 q+1 q+1。
然后我们正序扫描一遍所有询问。不难发现第 i i i次询问的答案为: 从 u u u开始只经过权值不超过 i i i的边所能到达的节点的最大点权,并将这个点的点权赋为 0 0 0。
是不是很熟悉这个模型?我们可以建立出一个关于边权的Kruskal重构树。每次查询的符合要求的节点均在一个子树中,这个子树的根可以倍增找到;找到之后,我们需要查询最小值并动态修改,可以采用dfs序+线段树来维护。
时间复杂度 O ( ( n + m ) log n ) O((n+m) \log n) O((n+m)logn),比LCT不知道可爱到哪里去了。
P5025
套路题。
首先考虑暴力做法。先 O ( n 2 ) O(n^2) O(n2)建图,然后缩点并执行一次拓扑排序( d p dp dp)。
考虑如何优化。不难发现这个连边有一个性质: 每个节点连向的点都在一个区间中。所以可以采用线段树来优化这个建图。线段树优化的建图同样可以缩点,只不过每个点本身都有一个权值。
我们可以通过二分找到每次连边的区间 [ l , r ] [l,r] [l,r]。时间复杂度为 O ( n log n ) O(n \log n) O(nlogn)。
P2048
大套路题,然而我不会。
令 p r e i = ∑ j = 1 i a j pre_i=\sum_{j=1}^i a_j prei=∑j=1iaj,那么不难得到 ∑ i = l r a i = p r e r − p r e l − 1 \sum_{i=l}^r a_i=pre_r-pre_{l-1} ∑i=lrai=prer−prel−1。于是我们将题目做一个转化——在序列中选 k k k对差在 l l l到 r r r之间的数,可以多次重复选择同一个数,使得每一对数的后者的 p r e pre pre减去前者的 p r e pre pre之和最大。
我们维护许多五元组 ( l , x , y , p o s , v a l ) (l,x,y,pos,val) (l,x,y,pos,val),表示选取的第一个位置 l l l,第二个位置在 [ x , y ] [x,y] [x,y]区间中;满足 p r e p o s − p r e l pre_{pos}-pre_{l} prepos−prel最大的位置为 p o s pos pos且这个最大值为 v a l val val。
我们将这些五元组扔进一个大根堆中。每次我们取出堆顶,并将这个区间拆分为两个形如 ( l , x , p o s − 1 , p o s ′ , v a l ′ ) (l,x,pos-1,pos',val') (l,x,pos−1,pos′,val′)的子五元组,分别重新计算这两个子区间的 p o s ′ pos' pos′与 v a l ′ val' val′。
采用RMQ来快速计算即可,时间复杂度为 O ( n log n + k log n ) O(n \log n+k \log n) O(nlogn+klogn)。
异或粽子这题只需要将RMQ求区间最大值改为可持久化Trie树上查询,时间复杂度为 O ( n log m + k log n log m ) O(n \log m+k \log n \log m) O(nlogm+klognlogm),其中 m m m为所有 a i a_i ai的最大值。