luogu 3899 湖南集訓 談笑風生

2021-09-27 08:01:46 字數 1689 閱讀 2993

題意

這題意太草了就不描述了,有黑眼鏡框和**暗示真惡毒啊

sol:

對於固定的a來說,每個b的貢獻是min⁡(

siza

,siz

b)−1

\min(siz_a,siz_b)-1

min(si

za​,

sizb

​)−1

考慮a是b的祖先和b是a的祖先兩種情況(把min去掉)

1.對於b是a的祖先,明顯答案是min⁡(

depa

−1,k

)×(s

iza−

1)

\min(dep_a - 1, k)\times(siz_a-1)

min(de

pa​−

1,k)

×(si

za​−

1)2.對於a是b的祖先,答案是∑de

pb−d

epa≤

ksiz

b−

1\sum_siz_b - 1

∑depb​

−dep

a​≤k

​siz

b​−1

對於第一種貢獻可以直接預處理子樹siz,對於第二種貢獻,考慮把深度作為下標建主席樹

考慮到b一定在a的子樹中,因此查詢a的子樹中dep區間的答案就可以了

接著是想怎麼用主席樹查詢子樹資訊。

明顯乙個子樹的點dfs序是連續的,因此子樹資訊可以用兩個dfs序字首資訊相減查詢,也就是根據dfs序建主席樹。

也可以直接線段樹合併。

#include

#include

#include

#define r register

const

int n =

3e5+7;

typedef

long

long ll;

inline

intmin

(int a,

int b)

int cnt =0;

struct node t[n*20+

7];void

ins(

int u,

int v,

int l,

int r,

int x,

int sw)

ll query

(int u,

int v,

int l,

int r,

int sl,

int sr)

int last[n]

, tot;

struct edge e[n*2]

;const

int inf =

3e5;

inline

void

add(

int u,

int v)

int n, q, dfn[n]

, rt[n]

, siz[n]

, dep[n]

;void

dfs(

int x,

int fa,

int depth)

}void

dfs0

(int x,

int fa)

return;}

intmain()

}

luogu3899談笑風生

設 t 為一棵有根樹,我們做如下的定義 給定一棵 n 個節點的有根樹 t 節點的編號為 1 n 根節點為 1 號節點。你需要回答 q 個詢問,詢問給定兩個整數 p 和 k 問有多少個有序三元組 a,b,c 滿足 題面真有趣 有乙個很套路的樹狀陣列離線做法 我在這題的部落格裡提過一遍 按照中序遍歷 d...

P3899 湖南集訓 談笑風生

傳送門 首先 a,b,c 肯定在一條鏈上。當 b 為 a 的祖先時,a 的子樹中所有與它不同的點都可以作為點 c 當 a 為 b 的祖先時,b 的子樹中所有與它不同的點都可以作為答案 我會說我以前根本沒寫過線段樹合併結果完全不知道錯在 麼 luogu judger enable o2 minamot...

P3899 湖南集訓 談笑風生

題目大意 n個節點的樹,q次查詢,每次查詢給出a,k求三元組的數量 a,b,c a,b,c 的定義為 a b均為c的祖先且距離 k 離線,啟發式合併線段樹,長鏈剖分當然都能過這題 這裡講講主席樹的做法 dfs序建樹 a為b的祖先時 查詢a子樹內深度 dep a k的節點的子樹和 b為a祖先時 乘法原...