BZOJ4777 七彩樹 線段樹合併

2021-09-12 03:59:15 字數 2882 閱讀 2070

題目鏈結

題意:給你乙個n

nn個點的樹,每個點有乙個範圍是1−n

1-n1−

n的權值,可能會有重複。每次問你乙個點的子樹內與它深度差不超過x

xx題解:

感覺一看就很線段樹合併,因為如果沒有不同權值的限制,只問乙個點子樹內與它深度差不超過x

xx的點的個數,就是乙個經典的線段樹合併的題了。

但是現在的問題是他問的是不同的權值個數,這個權值應該怎麼維護呢?現在的問題有兩個,第乙個是如果子樹內有多個相同的權值的話,怎麼防止算重;第二個是相同權值的話,顯然我們只要判斷深度最小的那乙個有沒有被包含就行了,那麼怎麼維護相同顏色在字數內出現的最淺深度。

這樣這個題就做完了,複雜度是o(n

logn

)o(nlogn)

o(nlog

n)。**:

#include

using

namespace std;

int t,n,m,hed[

100010

],cnt,fa[

100010

],num,num1,ans;

int root[

8000010

],root1[

4000010

],val[

100010

],dep[

100010];

struct edge

a[200010];

struct node

tr[8000010];

struct tree

tr1[

4000010];

inline

intread()

return x;

}inline

void

add(

int from,

int to)

inline

void

update

(int

&rt,

int l,

int r,

int x,

int y)

inline

void

update1

(int

&rt,

int l,

int r,

int x,

int y)

if(l==r)

int mid=

(l+r)

>>1;

if(x<=mid)

update1

(tr1[rt]

.l,l,mid,x,y)

;else

update1

(tr1[rt]

.r,mid+

1,r,x,y);}

inline

void

merge

(int

&rt,

int l,

int r)

rt=++num;

tr[rt]

.sz=tr[l]

.sz+tr[r]

.sz;

merge

(tr[rt]

.l,tr[l]

.l,tr[r]

.l);

merge

(tr[rt]

.r,tr[l]

.r,tr[r]

.r);

}inline

intquery

(int rt,

int l,

int r,

int le,

int ri)

inline

void

merge1

(int

&rt,

int l,

int r,

int le,

int ri,

int x)

int ji=rt;

rt=++num1;

tr1[rt]

.l=tr1[ji]

.l; tr1[rt]

.r=tr1[ji]

.r; tr1[rt]

.mn=tr1[ji]

.mn;

if(le==ri)

int mid=

(le+ri)

>>1;

merge1

(tr1[rt]

.l,tr1[l]

.l,tr1[r]

.l,le,mid,x)

;merge1

(tr1[rt]

.r,tr1[l]

.r,tr1[r]

.r,mid+

1,ri,x);}

inline

void

dfs(

int x)

}int

main()

for(

int i=

1;i<=num1;

++i)

for(

int i=

1;i<=cnt;

++i)

num=0;

num1=0;

cnt=0;

ans=0;

n=read()

; m=

read()

;for

(int i=

1;i<=n;

++i)

val[i]

=read()

;for

(int i=

2;i<=n;

++i)

dep[1]

=1;dfs(1

);for(

int i=

1;i<=m;

++i)

}return0;

}

主席樹 BZOJ 4771 七彩樹

感謝帶我飛的rxd大爺 我們先考慮不管深度限制可修改我們怎麼做 就是把每種顏色按照dfs序排列 然後給這些點都 1 但是相鄰兩個的lca處要 1 這樣子樹不同顏色數就是子樹和 然後我們把深度限制 看做按照深度的順序加點 加點我們需要維護什麼 每種顏色的序列 這個用set或平衡樹 在序列中插入 我們對...

BZOJ4771 七彩樹(主席樹)

點此看題面 考慮乙個子樹內所有點 dfs 序是連續的,所以我們可以將其轉化為序列然後用線段樹維護。又由於有深度限制,所以可以對不同深度建不同版本,使用主席樹。但是,本質不同顏色應該如何維護?考慮對於每一種顏色,如果有兩個該顏色的點同時出現,則相當於將這兩個點的權值分別加 1 而把它們 lca 的權值...

七彩樹 HYSBZ 4771線段樹合併

本題是查詢乙個節點x的字樹內深度與其相差不超過d的節點有多少種顏色。如果單純考慮有多少個點,應該如何求?此時我們應該考慮如何維護深度在乙個區間內且是x的後代的資訊。我們可以每個節點用一顆以下標為權值的線段樹來維護 後面記為線段樹x 用線段樹合併來完成所有資訊的處理。但如何查詢深度在乙個區間裡的資訊呢...