口嗨区
因为各种原因不想码或者或码不了,开一个博来记录思路。
在直接抄题解之前先口嗨一顿说明我读过题面。
https://www.luogu.com.cn/problem/P2286
平衡树模板题。
若树中只有同类数据直接插入。
出现异类数据查询前驱后继,选择更接近查询值的作为答案。
2020.5.2
https://www.luogu.com.cn/problem/P3850
单点插入,单点查询。
-
STL大法好 ! T6: 单点插入,单点查询
-
分块大法好 ! T6: 单点插入,单点查询
-
平衡树。
根据输入给出的位置,可得插入数的前驱后继。
用fhq 按子树大小分裂维护数列。
插入一个数 = 后继~结尾所有数权值+1,新建一权值为前驱+1的节点并插入。
插入时的过程- 按前驱权值分裂。
- 右树所有点权值+1。
- 新建节点并插入。
可发现插入新节点之后,不会影响树的性质。装上脑子一想之后发现根本没有必要维护权值。
二叉搜索树的形态就可反映权值大小关系。
维护权值实际上对按排名分裂的结果没有任何影响。
我是傻逼,学到许多。
2020.5.2
https://www.luogu.com.cn/problem/P3224
需要查询第 k 小值,则必须维护点集。
怎么暴力怎么来,先考虑维护 n 个平衡树,表示与各点联通的点集。
- 查询操作 直接查询对应平衡树中第 k 小。
复杂度 log n - 合并操作 枚举 x ,y 两棵树中的点, 将其对应点集两两合并。
大概长上面的样子,单次复杂度 n^2 log n (枚举 + 平衡树insert)。for nodex in x: for nodey in y: tree[nodex].insert(nodey) tree[nodey].insert(nodex)
发现瓶颈是点集的合并。由于查询操作已不可优化,考虑优化合并部分。
手玩合并过程,观察可知,合并后各点 对应点集相同。
再推广一下,两个联通点对应点集相同,经过多次合并后仍相同。
维护多个相同的点集 显得有些多余。
发现这玩意长得有点像并查集。
类比并查集的结构,可得到一种维护方法。
维护每一个节点对应点集的树根。
合并时将较小树的点暴力转移到较大树上(类似按秩合并),并将被转移的节点的根更新。
若按秩合并可保证最多只出现n次 insert操作,否则枚举会变成n^2级别。
维护根的关系时使用并查集。
或者直接写一个LCT水过去,就没有这么多事事了。
2020.5.2
http://www.lydsy.com/JudgeOnline/problem.php?id=4998
看起来很有tarjan的感觉。
若加边后,出现一个环,就将这条链split出来,再将链上的所有点摁到一个超级点里。
更新超级点的size 为 其中点的size, 更新其中点的belong。
查询时,两点在同一超级点中,就输出size。
2020.6.7
http://www.lydsy.com/JudgeOnline/problem.php?id=2959
上面那道题的加强版。不看样例还以为是牛逼题,先喷一波狗屁不通题面描述。
如果按照题目给出要求:
为了安全起见,每条跑道都需要设定一个方向,这条跑道只能按照这个方向单向通行。最多的刷卡次数即为在任意设定跑道方向,按照任意路径从A地点到B地点能刷卡的最多次数。
显然,如果进入了一个超级点,可以在里面绕圈圈刷卡。
观察样例可知:
- 可以在一个点里绕圈圈。
- 到达终点之后不一定立即停下,可以继续绕圈圈再回来。
那这题就贼水了。
两点之间的答案即为 两点路径上所有点,
所在超级点的size之和。
同上题维护即可。