主题

主题

 
   

正统树分块

  • 扯淡

在之前的非正统树分块中,我们发现,如果树块保证是一个连通块的话,在面对菊花图的时候束手无策。

要突破菊花图的限制,关键在于对树块的调整。如果树块始终是连通块又不做一些手脚的话,就做不到O(sqrt(n))。

正统树分块则是一种 通过不保证树块连通 使得树块大小均衡的方法。


  • 举个例子

1086: [SCOI2005]王室联邦

原题:http://www.lydsy.com/JudgeOnline/problem.php?id=1086

Description

  “余”人国的国王想重新编制他的国家。他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成

员来管理。他的国家有n个城市,编号为1..n。一些城市之间有道路相连,任意两个不同的城市之间有且仅有一条

直接或间接的道路。为了防止管理太过分散,每个省至少要有B个城市,为了能有效的管理,每个省最多只有3B个

城市。每个省必须有一个省会,这个省会可以位于省内,也可以在该省外。但是该省的任意一个城市到达省会所经

过的道路上的城市(除了最后一个城市,即该省省会)都必须属于该省。一个城市可以作为多个省的省会。聪明的

你快帮帮这个国王吧!

Input

  第一行包含两个数N,B(1<=N<=1000, 1 <= B <= N)。接下来N-1行,每行描述一条边,包含两个数,即这

条边连接的两个城市的编号。

Output

  如果无法满足国王的要求,输出0。否则输出数K,表示你给出的划分方案中省的个数,编号为1..K。第二行输

出N个数,第I个数表示编号为I的城市属于的省的编号,第三行输出K个数,表示这K个省的省会的城市编号,如果

有多种方案,你可以输出任意一种。

Sample Input

8 2

1 2

2 3

1 8

8 7

8 6

4 6

6 5

Sample Output

3

2 1 1 3 3 3 3 2

2 1 8


个人解法:

如上也给出了正统树分块的定义吧。

就拿WerKeyTom_FTD大爷的说法好了——

  1. 除根节点所在块以外,每一块内深度最小的结点的父亲相同。这个父亲被称之为该块的块顶,其中特别的根节点也是块顶。

  2. 每一块内非深度最小的结点的父亲一定与其处于同一块中。 

  3. B<=每块大小<=3B。B是常数。

这也是题目的要求。块顶就是“省会”。B就是题目中的省管辖的市的个数。

注意的是(在题目中也说了),块顶不一定在块中。


  • 实现方法

仍然是DFS。

我们维护一个栈。在所有子树被搜索完之后压栈。同时我们记录当前DFS的时候的栈顶,它也是搜索当前节点子树的栈底bottom。

如果一棵子树搜索完之后,栈中元素(注意是栈顶top减去我们记录的bottom)超过了B,我们就把bottom到top的所有元素放到同一个栈的。

不难证明这个算法的正确性。

之后考虑块的大小:

  1. 我们在搜索这一个子树的时候,栈中元素个数小于B,搜索上来栈中元素小于B,然后就会合并。这样大小不会超过2B。

  2. DFS结束之后。剩余的部分会和最后一个块连通。但是这一部分元素个数小于B。把这一部分加入到最后一个块(也就是根所在的块)中,这一个块不会超过3B。

于是块的大小在[B,3B]。


  • 代码如下

其实网上很多,可以找一些看看。

https://code.csdn.net/snippets/2215416

成功跻身于BZOJ第一页……


 
 
评论