BZOJ 1095 捉迷藏 動態點分治 點分樹

2021-08-11 06:32:27 字數 2918 閱讀 4449

1095: [zjoi2007]hide 捉迷藏

time limit: 40 sec memory limit: 256 mb

submit: 4152 solved: 1756

[submit][status][discuss]

description

捉迷藏 jiajia和wind是一對恩愛的夫妻,並且他們有很多孩子。某天,jiajia、wind和孩子們決定在家裡玩

捉迷藏遊戲。他們的家很大且構造很奇特,由n個屋子和n-1條雙向走廊組成,這n-1條走廊的分布使得任意兩個屋

子都互相可達。遊戲是這樣進行的,孩子們負責躲藏,jiajia負責找,而wind負責操縱這n個屋子的燈。在起初的

時候,所有的燈都沒有被開啟。每一次,孩子們只會躲藏在沒有開燈的房間中,但是為了增加刺激性,孩子們會要

求開啟某個房間的電燈或者關閉某個房間的電燈。為了評估某一次遊戲的複雜性,jiajia希望知道可能的最遠的兩

個孩子的距離(即最遠的兩個關燈房間的距離)。 我們將以如下形式定義每一種操作: c(hange) i 改變第i個房

間的照明狀態,若原來開啟,則關閉;若原來關閉,則開啟。 g(ame) 開始一次遊戲,查詢最遠的兩個關燈房間的

距離。input

第一行包含乙個整數n,表示房間的個數,房間將被編號為1,2,3…n的整數。接下來n-1行每行兩個整數a, b,

表示房間a與房間b之間有一條走廊相連。接下來一行包含乙個整數q,表示操作次數。接著q行,每行乙個操作,如

上文所示。

output

對於每乙個操作game,輸出乙個非負整數到hide.out,表示最遠的兩個關燈房間的距離。若只有乙個房間是關

著燈的,輸出0;若所有房間的燈都開著,輸出-1。

sample input

1 22 3

3 43 5

3 66 7

6 8g

c 1g

c 2g

c 1g

sample output

4 hint

對於100%的資料, n ≤100000, m ≤500000。

啊總算a了這道動態點分治了, 感覺點分樹這個名字好高大上的樣子…

相比於原來的點分, 動態點分治是建了一棵點分樹, 每個重心向它子樹里下一層重心連邊, 就成了一棵點分樹, 感覺跟支配樹的構造有點相似. 由於重心所以樹高是log級別的, 所以暴力跳支配樹fa.

第一次寫引用了黃學長的**…

順便粘一下hzwer的題解.

一開始寫的可並堆感覺自己快炸了…

其實這種做法不難。。。就是**長。。。

把每次分治的重心連成一棵樹,樹的深度是logn,每次修改乙個結點只影響它到樹根的一條鏈

這題具體實現的時候要維護三層堆

c.每個重心存所有子樹到其距離

b.每個重心存各個子樹最大值,即子結點堆c的最大值

a.全域性乙個堆,維護答案最大值,存每個堆b的最大值和次大值之和

樹上距離用rmq來求比較優越2333

**還是很清晰的, 雖然有180行….

#include

#include

#include

#define boc register char

#define acce register int

#define prio priority_queue

using

namespace

std;

const

int p = 22;

const

int inf = 1e9 + 7;

const

int maxn = 1e5 + 5;

const

int dblmaxn = 2e5 + 10;

int n, num, tot, idx, sum, root, t;

char ss[2];

bool vis[maxn], sta[maxn];

int st[p][dblmaxn], lg[dblmaxn], in[maxn], h[maxn], dep[maxn], f[maxn], fa[maxn], siz[maxn], pw[p];

inline

const

int read()

struct edgee[dblmaxn];

struct heap

inline

void erase(int x)

inline

void pop()

inline

int top()

inline

int size()

inline

int stop()

}a, b[maxn], c[maxn];

inline

void add(int u, int v)

void dfs(int u, int tfa)

}void getrt(int u, int tfa)

f[u] = max(f[u], sum - siz[u]);

if (f[u] < f[root]) root = u;

}void divi(int u, int dfa)

}inline

int query(int u, int v)

inline

int dis(int u, int v)

inline

void turn_off(int u)

}u = f;

}}inline

void turn_on(int u)

}u = f;

}}inline

void init()

int main()

else

}}

點分樹 ZJOI2007 捉迷藏

門 點分樹不卡常就別想過了。問樹中最遠黑點對距離 帶修改點分樹入門作 原圖先亂跑一次點分治,儲存點分治的每個root之間的父子關係,得到一顆點分樹。然後我們的原圖除了求dis就可以不管了 學習題解中不認識的大佬所說的套路 點分治得到點分樹 每個點用s1,s2 s 1,s 2 s1 s2 兩個資料結構...

動態點分治 bzoj 3730,bzoj 1095

總結一下動態點分治的模板。對於乙個樹,把它點分的同時記錄每個點的所有父親 logn個 並記錄點距其父親的距離。具體實現就是dfs的時候fa x dep x u,dis x dep x d bzoj1095 您需要寫乙個程式支援反轉點的顏色,求距離最遠的黑色點對的距離。解析 在每個點u存乙個堆st記錄...

bzoj4012 動態點分治 卡常數

這是一種型別的動態點分治 動態點分治,關鍵還是要在均攤n的空間複雜度記憶體下所有東西。這個就要充分利用stl,比如vector 每乙個點存以這個點為根點分治的資訊。對於詢問乙個點的路徑時,就是沿著點分治樹,不斷朝fa走,每走一層統計一下,因為分治樹可以保證在log層內,時間複雜度同階 卡常數無優化 ...