qbzt网格图路径问题——题解

题目内容:

  给定一个长n高2的网格图,如下图:

  

 

 

有三种操作:

    1、删除一条边

    2、将一条删除的边再加回来

    3、询问从一个点到另一个点的不同路径数(不可经过重复边)

算法复杂度要求不能大于 n log n

(由于只有题面,没有输入格式和数据,所以在此只讲一下思路)

    正解是用线段树维护。

先给网格图标上号:

  

 

 

 对于线段树上的节点,若它维护的区间为[l,r],则它就对应一个l~r的网格图G:

 

 

 a1、a2、a3、a4分别代表G的左上、右上、左下、右下方的点。同时有布尔变量b1~b6 ,bi表示ai连向外面图部分边的有(1)无(0)(i<=4),b5表示a1-a3这条边的有无,b6表示a2-a4这条边的有无。

有6变量c1~c6,表示在图G中:

  c1:从a1到a2的不同路径数

  c2:从a1到a4的不同路径数

  c3:从a3到a2的不同路径数

  c4:从a3到a4的不同路径数

  c5:从a1到a3的不同路径数

  c6:从a2到a4的不同路径数

  c7:是否有一条只走上部分边的路径可由a1到达a2

  c8:是否有一条只走上部分边的路径可由a3到达a4

  

  当G的大小为1*2时,此时a1a2重合,a3a4重合,各个变量的值很容易得出,故线段树的叶子结点有初始值。

 

  考虑线段树合并区间向上求的操作:

假设要将区间[l,mid](左)[mid+1,r](右)合并成[l,r](新),对节点的变量一次考虑:

1、对于b:

  显然,新b1=左b1,新b2=左b2,新b3=右b3,新b4=右b4,新b5=左b5,新b6=右b6

2、对于c,要仔细考虑一下:

 

 

 为了便于叙述,将新G的几条关键边的位置记为e1~e4。

对于新c7,新c8,一眼就能看出来怎么维护,故不多说。

 

对于新c1,路径的形式要么为左a1——左a4——e3——右a3——右a4,得新c1=左c1*右c4*左b4;

  要么为左a1——左a2——e1——右a1——右a4,得新c1=左c2*右c1*左b2。

  故新c1=左c2*右c1*左b2+左c1*右c4*左b4。

对于c2~c4,可同理分析。

 

对于c5,有两种情况:

  一是路径的所有边都在左图,那么新c5=左c5;

  二是有路径的边出现在右图,那么此时一定会经过e1和e3,又因为要保证路径的边不重复,所以有新c5=左c7*左b2*右c5*左b4*左c8

  所以新c5=左c7*左b2*右c5*左b4*左c8+左c5

对于c6,可同理分析。

 

接下来再考虑如何得到答案。

对于询问的两个点u,v,可以先得到他们对应的区间[l,r]

 

 

 首先想到的就是在线段树中找到[l,r]的答案。但这是不全的,因为线段树中得到的区间[l,r]的答案中的所有路径都是在图[l,r]内部的,但答案还有路径“出图的情况”,如下图:

 

 

 

其实这个也很好办,因为整个图的高只有2,所以"出图”无非只有两种情况:从左边出(即为上图),从右边出。

  以从左边出为例:

  显然要满足[l,r]对应的b1和b3都等于1,即要有能出图的一对边,这时很容易就想到答案为[1,l-1]的c6*b2*b4。

  从右边出同理。

最后这道题就解出来了。其实只要能弄明白线段树的维护信息,这道题就迎刃而解。这些维护信息,多半是由需求而生的。其实说实话,在写这篇题解时,有很多变量也是我在需求下想到的。

 

    

posted @ 2020-04-04 18:24  千叶繁华  阅读(275)  评论(0编辑  收藏  举报