首页 > 代码库 > BZOJ4515 SDOI2016 游戏

BZOJ4515 SDOI2016 游戏

  题目:
   Alice 和 Bob 在玩一个游戏。
  游戏在一棵有 n 个点的树上进行。最初,每个点上都只有一个数字,那个数字是 123456789123456789。
  有时,Alice 会选择一条从 s 到 t 的路径,在这条路径上的每一个点上都添加一个数字。对于路径上的一个点 r,
  若 r 与 s 的距离是 dis,那么 Alice 在点 r 上添加的数字是 a×dis+b。有时,Bob 会选择一条从 s 到 t 的路径。
  他需要先从这条路径上选择一个点,再从那个点上选择一个数字。
  Bob 选择的数字越小越好,但大量的数字让 Bob 眼花缭乱。Bob 需要你帮他找出他能够选择的最小的数字。
  数据范围:10^5
    分析:
     令p(i)为i的下标(数组中的位置)。考虑一条链的情况:另s<t,容易发现a*dis+b是一个一次函数,带入dis=p(i)-p(s);
  化简后得到f(p(i))=a*p(i)-a*p(s)+b也是一个一次函数,而且只和p(i)有关。对于任意一个点k,如果该点在f(p(k))取得最小值,

  当且仅当其它的一次函数g(p(k)),u(p(k)).....均大于f(p(k)),我们用图像表示,容易发现这是一个类似半平面的东西。

  那么我们可以考虑用线段树维护每个点取得最小值的线段。我们将标记永久保存,对于任意一条新加入的线段,我们在线段树

  上找到它应该在的位置,因为是一次函数,所以最多是一个交点,最少没有交点,那么我们分类讨论:

    1.如果没有交点,或者交点不在这个修改的范围里面,那么又有两种情况,一种是在任意位置都比当前标记的线段得到的值要大,这时候很显然这条新的线段没什么用,可以直接忽视。否则就是比当前标记所得到的值要小,那么我们用新线段去替换旧线段。这是O(1)的

    2.如果有交点并且交点在区间里面,那么容易看出在交点的一侧至少有这个区间的一半的长度。也就是说,在这个交点的一侧我们一定可以用第一类情况去处理,另一侧我们可以递归处理,因为每次都有一半被处理,由二分知这是O(logn)的。

  由线段树和二分知每次修改的时间复杂度是O(nlog^2n)的。

  对于每个询问,我们从上遍历到下,同时记录取到的最小值,这时候标记也不要下移,其它跟普通线段树是一样的,容易看出这是O(logn)的

  所以在链上处理两个询问的时间复杂度是O(nlog^2n)的.

  如果不是链而是树呢?我们重新分析:首先任意一条树上从s到t的路径我们都是能看作从s到LCA(s,t),再从LCA(s,t)到t。另任意一个点x的深度为dep(x),那么在s到LCA(s,t)中的某个点j,它到s的距离dis=dep(s)-dep(j),带入原式,得到f(dep(j)) = a*(dep(s)-dep(j))+b =-a*dep(j)+a*dep(s)+b.同样对于任意LCA(s,t)到t的路径中的点j,到s的距离为dis=dep(s)-2*dep(lca)+dep(j).同样带入,结果我就不写了。又因为这是一棵树,所以用树链剖分来使他退化成链。然后用在链上解决这个问题的方法解决这个问题。

  因为在链上问题的基础上把问题强行放到了树上,所以复杂度多了个log,但因为常数比较小(这里我提供常数比较小的解释:一.因为一个线段的交点正好在区间的左数第二个点和右数第二个点的几率特别小,所以每次二分不一定要到末尾才结束,所以一般可以把交点平均在二分中间时刻停止,因此这里有个二分之一的常数;二.线段树不一定是最坏情况(每层都有两个点),所以这里有个约3/4的常数,又由于树链剖分不一定是最坏情况,所以这里又有个约1/2的常数,多亏了出题人良心),所以这题O(nlog^3n)是可以通过的。

BZOJ4515 SDOI2016 游戏