洛谷 P3899 湖南集訓 談笑風生

2021-10-07 09:34:20 字數 2791 閱讀 3375

原題鏈結

題目大意

有一棵 n

nn 個節點的有根樹,有 m

mm 組詢問

每次詢問給出 a,k

a,ka,

k,求有多少個三元組 (a,

b,c)

(a,b,c)

(a,b,c

),滿足 a,b

a,ba,

b 都是 c

cc 的祖先,並且 a,b

a,ba,

b 之間的距離不超過 kkk

剛開始沒有思路,看了題解的分類討論後發現可以很輕鬆地轉化為線段樹合併

解題思路

首先,定義 d

xd_x

dx​ 為點 x

xx 的深度(根節點的深度為 111)

s

xs_x

sx​ 為點 x

xx 的子樹大小(包括 xxx)

考慮兩種情況

b

bb 是 a

aa 的祖先:那麼 b

bb 就必須在 a

aa 到根的路徑上。可能方案數就是 min⁡(

da−1

,k)×

(sa−

1)

\min (d_a-1,k) \times (s_a-1)

min(da

​−1,

k)×(

sa​−

1)b

bb 在 a

aa 的子樹中:方案數就是 ∑dx

∈[da

+1,d

a+k]

(sx−

1)

\sum\limits_ (s_x-1)

dx​∈[d

a​+1

,da​

+k]∑

​(sx

​−1)

,注意這裡的 x

xx 必須在 a

aa 的子樹中。

我們可以用線段樹合併維護子樹資訊來實現操作2,最終的答案就是兩方案數之和

#include

#include

using

namespace std;

const

long

long maxn=

300000+10

,inf=

0x3f3f3f3f

;const

long

long maxm=

6000000+10

;long

long d[maxn]

,s[maxn]

;long

long nxt[maxn<<1]

,to[maxn<<1]

;long

long sum[maxm]

,ls[maxm]

,rs[maxm]

;long

long root[maxn]

,head[maxn]

;long

long n,m,idcnt,edgecnt=1;

inline

void

add(

long

long x,

long

long y)

inline

long

long

read()

while

(ch>=

'0'&& ch<=

'9')s=

(s<<3)

+(s<<1)

+(ch^48)

,ch=

getchar()

;return s*w;

}inline

void

push_up

(long

long x)

void

modify

(long

long

&x,long

long l,

long

long r,

long

long pos,

long

long v)

long

long mid=

(l+r)

>>1;

if(pos<=mid)

modify

(ls[x]

,l,mid,pos,v)

;else

modify

(rs[x]

,mid+

1,r,pos,v)

;push_up

(x);

}long

long

merge

(long

long x,

long

long y)

long

long

query

(long

long k,

long

long l,

long

long r,

long

long x,

long

long y)

void

dfs(

long

long x,

long

long fa)

modify

(root[x],1

,n,d[x]

,s[x]-1

);}int

main()

dfs(1,

0);while

(m--

)return0;

}

洛谷P3899 湖南集訓 談笑風生

設t 為一棵有根樹,我們做如下的定義 設a和b為t 中的兩個不同節點。如果a是b的祖先,那麼稱 a比b不知道 高明到 去了 設a 和 b 為 t 中的兩個不同節點。如果 a 與 b 在樹上的距離不超過某個給定 常數x,那麼稱 a 與b 談笑風生 給定一棵n個節點的有根樹t,節點的編號為1 到 n,根...

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祖先時 乘法原...