【初識】樹上分塊


樹上的有些問題是可以用樹剖或者動態樹解決的,但是他們有一個動同點就是:不連通。

  • 比如求u到v的路徑權值和,或者最大值:

                u到v可能對應了多個鏈,這多個鏈在對應的數據結構(假設是線段樹)上面對應不同的區間。但是線段樹上這幾個區間的不連續並不影響我們得到答案。

                (當然求子樹的信息話是連續區間)

那么如果我們遇到的問題要求區間連續呢,比如求u到v的路徑上點的權值有多少種?如果不連續就得處理鏈與鏈之間的關系。顯然這些點得待在一起,如果樹剖很難維護鏈與鏈之間的關系。

樹分塊,大概有這樣的一些方法: 

  • 王室聯邦分塊法:可以保證每個塊的大小和直徑都不超過2√N1,但是不保證塊聯通 
  • DFS序分塊法:首先是好寫(畢竟轉化成了序列問題),嚴格保證塊大小√N,但是不保證直徑,也不保證聯通。處理子樹信息比較方便 
  • size分塊:檢查當前節點的父親所在塊的大小,如果小於√N就把當前節點加入進去,不然新開塊。塊大小最壞√N,保證塊內聯通,還保證直徑,多么優美啊可惜不能保證塊個數(一個菊花圖就死了)

 

王室聯邦分塊,假設每個塊的數量個數為[B,3B].

     如何分組可以看,裸題 BZOJ1086 王室聯邦。 

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int const maxn=2010;
int q[maxn],group[maxn],rt[maxn],top;
int Laxt[maxn],Next[maxn],To[maxn],cnt,ans;
int n,B;
void init()
{
    ans=0;  top=0;  cnt=0; 
    memset(Laxt,0,sizeof(Laxt));
}
void add(int u,int v)
{
    Next[++cnt]=Laxt[u];
    Laxt[u]=cnt;
    To[cnt]=v;
}
void dfs(int u,int pre)
{
    int Now=top;
    for(int i=Laxt[u];i;i=Next[i]){
        if(To[i]!=pre){
           dfs(To[i],u);
           if(top-Now>=B) { rt[++ans]=u; while(top!=Now) group[q[top--]]=ans;}
        }
    } q[++top]=u;
}
int main()
{
    while(~scanf("%d%d",&n,&B)){
        int u,v; init();
        for(int i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            add(u,v);add(v,u);
        }   dfs(1,0);
        while(top) group[q[top--]]=ans;  printf("%d\n",ans);
        for(int i=1;i<=n;i++) printf("%d ",group[i]);printf("\n");
        for(int i=1;i<=ans;i++) printf("%d ",rt[i]);printf("\n");
    } return 0;
}
View Code

 

再稍微介紹一下王室聯邦分塊是干嘛的:

     我們dfs,把子樹中大於B的分為一組,剩余的(肯定小於B)上傳分到父親那組。由於父親那組大於B,加進去小於3B。每一組即比較平均了,B的大小會影響空間和時間的優劣,需要根據題目給定的時間和空間,時間多空間小就B大,空間多時間少就B小。從而來決定B的大小。

     這樣分塊是為了莫隊的排序,而不是預處理保存信息。比如,(u,v) 轉移到(a,b),由於u和a或在一個組里面,即距離不太遠,轉移時間不太大。

 

例題: Count on a tree II ,SPOJ - COT2,代碼見這里

 求節點u到節點v路徑上節點數值的種類。 此題有很多種牛逼做法,見此處的整理

對於不要求在線的題,我們可以可以選擇莫隊算法:根據王室聯邦分塊來分塊排序,按順序轉移得到答案,可以參考這里的代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM