Educational Codeforces Round 129
E - Labyrinth Adventures
题目
https://codeforces.com/contest/1681/problem/E
n行n列的迷宫
1 | 55555 |
左下角第一层,然后它八临的第二层,再8临第三层
不同层之间有墙隔着,部分墙的位置有门, 每两层之间有恰好两个门, 一个是上下方向,一个是左右方向, 门是双向通的
q个询问两点之间最少的移动步数
范围
n 1e5
q 2e5
6s
512MB
题解
n很大显然无法建立图
但我们可以考虑如果是图会怎么做
首先如果没有任何阻挡,那么两点之间的曼哈顿距离为 走个直角, 因此如果两个同色,那么必然答案就是曼哈顿距离
那么就是考虑不同颜色
显然也不会 一个色不连续的走到,否则这段路径直接同色最短, 综上 如果 a < b , 那么a->b 的距离 = a->某个门-> a+1->某个门->a+2 ->某个门 -> ... -> b
再改改
位置pos -> 门(a,0) -> 门(b-1,0) -> 位置dst
位置pos -> 门(a,0) -> 门(b-1,1) -> 位置dst
位置pos -> 门(a,1) -> 门(b-1,0) -> 位置dst
位置pos -> 门(a,1) -> 门(b-1,1) -> 位置dst
如果我们能快速求两个门之间的最短距离就好了
直接考虑rmq的办法, 记录 (位置i,0/1号门, 2的幂次j距离, 0/1号门) 的最小距离
这样复杂度为$O(n \cdot log(n) )$ 的初始化和 $O( log(n))$ 的单次查询
代码
无
会的, 不想写了
F
题目
https://codeforces.com/contest/1681/problem/F
给到一个n个点的树, 边上有整数
记f(u,v) = 点u到点v简单路径上 只出现了一次的数字的个数
求对于所有u < v 的点对, f(u,v)的总和
边的值[1..n] 不需要自己离散化了
范围
n 5e5
6s
1024mb
题解
显然假设一条边上写的是 x
那么从贡献角度来讲, 它对答案的贡献是,左侧端点不再经过值为x边的点数 乘上 右侧端点不再经过值为x边的点数
问题呢, 如果我们通过叶子统计汇总,那么每个叶子上需要记录O(n)
个值的出现次数, 那显然就n 方了
那么我们考虑对于一个d, 在dfs时,不要影响到其它的块的办法
任意选一个点作为根,先考虑 dfs过程中经过了两个边为d
分别是(u0,v0,d) 和 (u1,v1,d)
那么 (u1,v1) 的贡献 = 以v0为根的d断开的联通块大小 乘上 以v1为根的d断开的联通块大小
而 以v为根的d断开的联通块大小 = v为根的子树大小 - sum{最近的d断开的 以v1/v2/v3/v4… 为根的树的大小}
这样 辅助数组 记录深搜过程中 上一个同边对应的点即可, 空间就是O(n),
还有一个问题, 如果是 dfs中首次出现的呢
这里的方法是对于每一个d 假装树的根的父节点连出去的就是d,即可
代码
https://codeforces.com/contest/1681/submission/158413431
1 |
|
总结
其实相当于线性数组的变性, 靠值来记录上一个同样值的位置, 不同的是线性可以直接坐标差得到中间的联通块, 而 树状可以dfs知道 到根最近的同样的值在哪, 而联通块的信息直接表示在根上