牛客練習賽58 F

2021-10-03 23:50:42 字數 1849 閱讀 5904

求帶單點修改的樹上兩點間任意子路徑長異或和。

路徑長等於路徑上所有異或和。

簡單模擬一下,可以發現。

奇數情況下,答案是偶數點異或和。

偶數情況下,就是正常的異或和。

偶數點異或和也很容易處理。

分深度奇偶樹狀陣列即可。

但是這是對於鏈的,不能直接dfs

dfsdf

s序,需要剖分一下。

但是我不會,所以去學了一下。

簡單意思就是:

孩子結點的子樹最大的作為重兒子。

每次優先跑重兒子,可以使得dfs

dfsdf

s序中重鏈都是連續的。

利用這個特徵,我們在處理的時候,每次跳到鏈頭,最後不斷處理詢問即可。

這其中:樹鏈剖分的複雜度是nlo

g2

nnlog^2n

nlog2n

不過我還有兩點疑問:

為什麼複雜度能保證,以及為什麼跳的時候要先跳鏈頭深度大的或者dfs

dfsdf

s序大的。

不過目前這不是重點,我就先鴿了(被迫先學了樹剖,最近明明在弄圖論)

單點更新,三個線段樹即可。

#include

#define for(i,a,b) for(int i=a;i<=b;i++)

using

namespace std;

const

int maxn =

2e5+

100;

vector<

int>g[maxn]

;int sz[maxn]

,son[maxn]

,dep[maxn]

;int dfn[maxn]

,top[maxn]

,fa[maxn]

;int a[maxn]

,cnt,n,m;

//剖分

void

dfs1

(int u,

int pre)

}void

dfs2

(int u,

int tr_top)

}//樹狀陣列

int c[maxn][3

];intlowbit

(int x)

void

change

(int x,

int d,

int id)

intquery

(int x,

int id)

//樹鏈剖分更新

void

update

(int x,

int c)

intquery

(int l,

int r,

int id)

// cout(dfn[l]

<=dfn[r]

)ans^

=query

(dfn[r]

,now)

^query

(dfn[l]-1

,now)

;else ans^

=query

(dfn[l]

,now)

^query

(dfn[r]-1

,now)

;//cout}int

main()

dfs1(1

,0);

dfs2(1

,1);

for(i,

1,n)

for(i,

1,n)

update

(i,0);

for(i,

1,m)

//cout

XOR TREE 牛客練習賽58 F 樹鏈剖分

這個問題很容易想到之間的關係,假設現在所要查詢的這條鏈上有v1 v2 vk個點,那麼第i個點的貢獻在抑或 現的次數xor為 於是,如果k為偶數的時候,我們直接求這條鏈上所有值的抑或xor和即可,樹鏈剖分就可以很好的維護了。所以考慮深度,會發現,深度奇偶不同的點一定是不相連線的,並且中間只隔了乙個點。...

牛客練習賽58

a 給你兩個序列ai,bia i,b i ai bi 然後讓你兩兩配對相加,使得最大值最小。貪心。乙個從大到小排,乙個從小到大排,直接相加。b給你乙個01字串,然後讓你找到最多的組,滿足每一組都有0和1。貪心。從前往後掃。遇到0和1是立馬累加,思路 一開始想得是每次挑出行和列中的最大值,然後累加,沒...

牛客練習賽58 D 迷宮

乙個n m迷宮,迷宮中每個格仔用0或1表示,0表示該格仔可以通過,1表示該格仔是個障礙物,牛妹站在格仔 1,1 出口在格仔 n,m 牛妹想要走出迷宮,但牛妹只會按以下策略走 牛妹當前所在的格仔稱為當前格仔 如果當前格仔右邊沒有障礙物,牛妹就向右走,否則轉到2。如果當前格仔下方沒有障礙物,牛妹就向下走...