點分樹 ZJOI2007 捉迷藏

2021-10-06 23:59:20 字數 2160 閱讀 3385

點分樹不卡常就別想過了。。。

問樹中最遠黑點對距離

帶修改點分樹入門作

原圖先亂跑一次點分治,儲存點分治的每個root之間的父子關係,得到一顆點分樹。然後我們的原圖除了求dis就可以不管了

學習題解中不認識的大佬所說的套路:

點分治得到點分樹

每個點用s1,

s2

s_1,s_2

s1​,s2

​兩個資料結構維護,依次容斥

修改和查詢都是樹高(logn)×

\times

×資料結構修改查詢複雜度

初始化可以視為n次修改

此題用堆維護

①第一種堆:維護當前節點的每個點分樹子樹中的maxdis

②第二種堆:維護當前節點的所有子樹到其點分樹father的dis

我們需要求的是某個節點作為中間點,它的兩個點分樹子樹中的maxdis之和最大,也需要用乙個堆來維護

技巧

此題堆需要刪除堆中間部分的數,可以多儲存乙個trash堆用來儲存要刪的數,用堆的時候判一下是否兩堆頂相同,相同彈掉即可

#include

#define re register

using

namespace std;

const

int n=

1e5+

10,m=

2*n,inf=

1e9;

int n,m;

int a[n]

;int head[n]

,nex[m]

,to[m]

,tot;

inline

void

build

(int u,

int v)

//--

namespace cutree

}void

dfs2

(int u,

int p)

}inline

intlca

(int x,

int y)

return dep[x]

?x:y;

}inline

intdis

(int x,

int y)

}//---

#define ap n*2+1

priority_queue<

int>t[n<<1]

,trash[n<<1]

;inline

void

add(

int u,

int w)

inline

void

del(

int u,

int w)

}inline

inttop

(int u)

inline

intsecond

(int u)

//---

int size,root,maxx;

int sz[n]

,fa[n]

;bool vis[n]

;void

find

(int u,

int f)

tmp=

max(tmp,size-sz[u]);

if(tmp}void

solve

(int u,

int f)

}inline

void

init()

//----

int last[n]

,pre;

inline

void

q_add

(int u)

}inline

void

q_del

(int u)

}char s[10]

;int

main()

init()

;for

(int i=

1;i<=n;i++

)q_add

(i);

int g=n;

scanf

("%d"

,&m)

;while

(m--

)else

}}

最後當然是加火車頭過的啦

ZJOI2007 棋盤製作

題目描述 西洋棋是世界上最古老的博弈遊戲之一,和中國的圍棋 象棋以及日本的將棋同享盛名。據說西洋棋起源於易經的思想,棋盤是乙個8 8大小的黑白相間的方陣,對應八八六十四卦,黑白對應陰陽。而我們的主人公小q,正是西洋棋的狂熱愛好者。作為乙個頂尖高手,他已不滿足於普通的棋盤與規則,於是他跟他的好朋友小w...

zjoi2007棋盤分割

西洋棋是世界上最古老的博弈遊戲之一,和中國的圍棋 象棋以及日本的將棋同享盛名。據說西洋棋起源於易經的思想,棋盤是乙個8 8大小的黑白相間的方陣,對應八八六十四卦,黑白對應陰陽。而我們的主人公小q,正是西洋棋的狂熱愛好者。作為乙個頂尖高手,他已不滿足於普通的棋盤與規則,於是他跟他的好朋友小w決定將棋盤...

ZJOI2007 報表統計

不想描述了,心累。兩個操作分別用splay和線段樹來維護 全域性的差值最小直接用splay在插入的時候維護前驅後繼即可 相鄰最小差值我們可以這樣搞 首先 用線段樹維護相鄰的最小值 可以注意到插入元素的操作,如果是在乙個元素之後反覆插入,這些元素之間更新出來的最小值是不會發生改變的。只有元素與元素之間...