UOJ 284 快樂遊戲雞(長鏈剖分)(單調棧)

2021-09-27 12:38:43 字數 1909 閱讀 4079

我tm就隨手一寫。

uoj速度榜rk4的同時,加上讀優之後uoj碼長榜第二,把fread優化去掉後就成碼長榜第一了???

某種意義上從側面證明了這個做法的優越性

考慮什麼時候能夠從s

ss走到t

tt,當且僅當死亡次數已經達到了路徑上的w

ww最大值,這個可以倍增求一下。

也就是說在死亡次數達到max⁡w

\max w

maxw

之前,我們只能一直死,那麼顯然我們希望能夠早死早超生。

維護乙個子樹內部按照深度排好序後對於w

ww的單調棧。顯然每次直接從棧頂貪心直到死亡次數足夠,然後再加上從s

ss走到t

tt的距離就是我們要的答案。

於是我們需要求單調棧從棧頂到棧底的字首和,但是顯然我們只能維護字尾和。

棧的合併實際上按照任意順序時間複雜度都是o(n

)o(n)

o(n)

,但是我們需要注意空間,為了空間小點,我們長鏈剖分之後按照dfs序分配空間即可。

用指標會非常好寫,陣列其實應該也挺好寫

對於每個詢問,利用二分找到單調棧會彈到**,然後xjb算一下答案即可。

**:

#include

#define ll long long

#define re register

#define cs const

namespace io

template

<

typename t>

inline t get()

inline

intgi()

}using

namespace io;

using std::cerr;

using std::cout;

using pii=std::pair<

int,

int>

;#define fi first

#define se second

cs int n=

3e5+7;

int n,q;

std::vector<

int> g[n]

;std::vector qry[n]

;int fa[20]

[n],mx[20]

[n];

int w[n]

,son[n]

,mxd[n]

,d[n]

;void

dfs1

(int u,

int p)

mxd[u]

=mxd[son[u]]+

1;}inline

intquery

(int u,

int to)

ll ans[n]

;struct node

;node p[n]

,arr[n]

;node *h[n]

,*t[n]

,*tp;

inline

void

ins(

int u,node c)

}inline

void

merge

(int u,

int v)

inline ll solve

(int u,

int v)

int dfn;

void

dfs2

(int u));

}signed

main()

dfs1(1

,0),

dfs2(1

);for(

int re i=

1;i<=q;

++i)cout<<<

"\n"

;return0;

}

uoj 207 共價大爺遊長沙

miaom又來做lct了!lych 無敵 由於不是很懂lct子樹資訊維護的那套理論,想了好久 搞得樹剖的子樹維護就會了一樣!首先是乙個很巧妙的轉化 將邊在鏈上轉化為這條邊能將鏈的頂點分開。給每組頂賦乙個隨機權,每次可以把邊斷掉,查詢每個聯通塊內權值異或和是否等於所有頂點權值異或和,就是子樹異或和。然...

UOJ207 共價大爺遊長沙

uoj 神題 給每個點對隨機乙個權值,把這兩個點的權值異或上這個隨機的值 用l ctl ct 維護子樹資訊,若子樹異或和為所有點對的異或和那麼就是答案 大常數 include define rg register define il inline define fill a,b memset a,b...

UOJ207 共價大爺遊長沙

link 我們知道一條邊被所有路徑經過就是其乙個端點的子樹中包含了所有路徑的一端。那麼我們可以給每條路徑的端點rand乙個隨機權值,然後用lct維護子樹異或和,查詢就是看子樹異或和是否等於所有隨機權值的異或和。lct維護子樹資訊 單點修改就是多維護乙個虛子樹資訊,改變虛邊的時候修改一下就好了。這個方...