【JZOJ5909点双+圆方树易错】【CSP-S2019模拟】10.29比赛总结

数据真水.jpg,没有调出来少了90分血亏。

比赛思路

传送门

  • T1(轻功):水DP
  • T2(开荒):伪虚树,对于相邻点计算贡献。链上的点权和用差分,计算到根的和。每一个点的点权的影响范围是它的子树,那么就根据DFS序维护和,区间修改,单点查询。
  • T3(跑商):刚开始以为是从任意一个点买,在任意一个点卖,推了半个小时之后感觉极其不可做。再看了看样例才发现是在起点买。然后就变成求最小值了。那么树的情况就是链剖。
    然后因为这是无向图,根据套路一般都要缩点缩环。我就随便缩了个边双。由于不能经过重复的点,这个边双自然就变成点双了。如果我们将点双的图构建出来的话,就可以在这个树上套一发链剖了。但是由于一个点可以在很多个点双里面,我就想到将每一个点双新建一个点,将它与所有的割点相连,割点负责沟通点双。
    为了建图方便不妨将点双与在它里面的所有点相连。
    通过以上的思考我就成功自己推了一遍圆方树(跪了Orz,完全没有想到原来这就是圆方树)。
    再看了看询问的形式,发现直接从一个点u经过一些点双,走到v,这条路径上的最小值就是答案。然后对于每一个点双要维护一个set(因为要修改),它的贡献就是它连向的点的最小值。
    到这里的时候就有一个问题,修改一个点,会把连向它(也就是它属于)的点双修改,如果一个点有很多个点双,那这样改是会T的。
    但是既然出题人都说数据水,那我不妨水一水,爆打40min后调了20min,时间就过了。交了一发90分WA了(不愧是水的数据)。

赛后消化

  • T3实际上,在圆方树上,方点代表点双,原点代表原图中的点,原点只能连向方点,方点只能连向原点。对于一个原点的修改,考虑到树的形态,只更新它的父亲,那么对于一个方点来说,它被它的所有儿子的修改更新到了,但是没有被它的父亲的更新影响到,所以只需要将父亲的贡献单独算上去就好了,这个单独的贡献在查询的时候O(1)算,修改的时候也只需要改一次。
  • 这个正解简单易懂,但是我却调了一个下午。
  • 我先是改我之前的WA90的程序。改了两个小时后无果,还是lyl告诉我是我的tarjan打错了。
  • 我在退栈的时候之前是
++tot;
while (d[d[0]]!=x) 
	insert0(d[d[0]],tot),d[0]--;
insert0(x,tot);
  • 但是如果d的里面还有另一个儿子,它与x在同一个点双里面,但是x的父亲也在这个点双里面,导致这个时候并不能弹出这个儿子的信息。但是我们将d直接退到了x,导致先前的儿子里面的东西被当做这个儿子的点双,实际上这个儿子的点双与其无关
++tot;
while (1) {
	insert0(d[d[0]],tot),d[0]--;
	if (d[d[0] + 1] == e[i]) break;
}
insert0(x,tot);
  • 实际上应该这样。
  • OI路上总不是一帆风顺的。
  • 改正解的时候又刚了一个多小时。
  • 实际上我直接用之前的程序,在方点的初值上是所有的原点,而不是它的儿子Orz,然后又水过了成吨的分数。

总结

  • 今天真是跌宕起伏的一天啊。
  • Tarjan的一些特殊情况总是想不到,要多多练习才好。
  • 解题的思路最近比较清晰,当然也有是题目难度的因素在里面。
  • 理解题意的时候一定要阅读样例,不要为了省时间而不看样例。
  • 注意初值。
原文地址:https://www.cnblogs.com/DeepThinking/p/13090931.html