二维平面点的转化
对于静态的二维问题都可以转化为动态的一维问题。——\(lxl\)
数据结构的问题放在二维平面上思考是一个很好的方法。
第一次一脸懵,第二次听终于明白了/kk
模型
很多题都可以转化到这个模型上。
给定一个二维平面,上面有 \(n\) 个矩形,每个矩形的坐标为 \([1, n]\)
有 \(m\) 次查询,每次查询一个二维平面上的点被多少矩形覆盖。
对于这类问题,可以这样考虑。
每次查询对应的是二维平面上的一个点。
维护一条扫描线,从左向右扫过去,当扫到一个矩形的时候,把矩形内的点都 +1,这样就可以直接查询每个点被多少个矩形覆盖了。
怎么实现?
先将询问都离线下来,然后按照横坐标排序。
对纵坐标建一棵线段树。然后依次从左到右扫过去。
如果碰到一个纵坐标为 \(y_1, y_2\) 矩形的左端点,就在线段树上对区间 \([y_1,y_2]\) 加 1,如果是右端点,就对区间 \([y_1, y_2]\) 减 1。如果碰到的是查询,直接单点查询就好了。
栗题
T1
给定长为 \(n\) 的序列, \(m\) 次查询区间内有多少个值只出现一次。
考虑每个数的贡献,可以先预处理出每个数左边和右边第一个与它相同的数在哪儿。
设这两个数分别为 \(pre_i, nxt_i\) ,那么这个数只会对左端点在 \((pre_i, i)\) ,右端点在 \((i, nxt_j)\) 的查询有贡献。
构造二维平面,一维为左端点,另一维为右端点,每次查询对应着平面内的一个点,每个数的贡献对应着一个二维平面的一个平面,那么问题就转化成了每个点被多少个矩阵覆盖的问题了。
T2
树,点有颜色,求多少条树上简单路径满足上面的颜色互不相同。
每种颜色出现次数 \(\leq 20\), \(n\leq 10^5\)
solution
如果有两个相同颜色的点,一条合法的路径两个端点一定不会分别在这两个点的子树内,选了构成的路径一定经过这两个颜色相同的点。
对于子树考虑 \(dfs\) 序处理。
两个相同颜色端点(不互为祖先)的子树都分别对应着 \(dfs\) 的一个区间,如果路径的左右端点在这个分别在这两个区间的话那么这条路径就不合法。
如果一个点与它一个祖先颜色相同,那么不合法的路径就是从该点的子树内选一个点,祖先的子树外选一个点,对应到 \(dfs\) 序上就是一段连续的区间和两端区间。
构造二维平面(一维为左端点,一维为右端点),每条路径都对应这二维平面内的一个点,每两个颜色相同的不互为祖先的点能形成的不合法的路径都是一个矩形,互为祖先的就形成两个矩形。
初始最大的矩形(所有的路径)值为 1,然后将构成的每个小矩形设为 0,最后统计有多少个 1 就好了。