洛谷P5002 專心OI 找祖先

2021-10-03 17:53:02 字數 1735 閱讀 4904

題目描述

這個遊戲會給出你一棵樹,這棵樹有nn個節點,根結點是rr,系統會選中mm個點p_1,p_2…p_m ,要imakf回答有多少組點對(u_i,v_i)的最近公共祖先是p_i 。imakf是個小蒟蒻,他就算學了lca也做不出,於是只好求助您了。imakf畢竟學過一點oi,所以他允許您把答案模 (10^9+7)(

9 +7)

輸入格式

第一行 n , r , m

此後n-1行 每行兩個數a,ba,b 表示a,ba,b之間有一條邊

此後1行 m個數 表示p_i

輸出格式

m行,每行乙個數,第ii行的數表示有多少組點對(u_i,v_i)的最近公共祖先是p_i

題解: 本來想寫點求lca的題,看見這個標籤有lca就進來了

然而這題和求lca一點關係沒有

簡單地分析了一下題目,兩個兩個求lca再判斷方法必然會tle,於是我們考慮一些其他的做法。廢話

首先,兩個點的lca如果是p的話,我們不難發現,如果有乙個點不是p,那麼這兩個點必然位於p的兩個不同子樹中,否則就會有乙個深度更深的爸爸取代他。

於是我們可以考慮,對於p的每乙個子樹,必有(size[p]-size[son])*size[son]個合法解,這個式子代表的是p的這棵子樹中的每乙個點和其他子樹中的每乙個點構成一對,因為不在一棵子樹中,所以p必然是他們兩個的lca。把這些加起來之後,p的子樹中的任何乙個點和p都可以構成一對,而由樣例可以知道,p和p自己也是一對,所以再在上面的式子基礎上加上size[p]。此題就結束了。 因為(u,v)(v,u)算兩組解,所以這樣必然是對的,上** (m比n大,所以可以先全算出來啦)

#include

#include

#include

#include

#define fo(i) for(int i=1;i#define fo(j) for(int j=1;j<=m;j++)

using

namespace std;

const

int n=

500005

;const

int m=

2000003

;const

int modd=

1e9+7;

int n,m,s,tot;

int head[n]

;int dep[n]

,ans[n]

;struct nodebian[m]

;struct nodedian[n]

;inline

intread()

while

(ch>=

'0'&&ch<=

'9')

return x*f;

}inline

void

add(

int x,

int y)

void

dfs(

int xx,

int fa)}}

inline

intsolve

(int xx)

}return ans;

}int

main()

dian[0]

.dep=0;

dfs(s,0)

;for

(int i=

1;i<=n;i++

) ans[i]

=solve

(i);

fo(j)

return0;

}

專心OI 找祖先

題解 假設我們找到點u 1.這些點對不跨越u,即其中有乙個點一定是u ans1 2 times size left u right 1 2.這些點不跨越u u的所有子樹的大小相乘即是答案。w為子樹個數。ans2 sum limits w w right times size left right s...

洛谷 P1469 找筷子

經過一段時間的緊張籌備,電腦小組的 rp餐廳 終於開業了,這天,經理lxc接到了乙個定餐大單,可把大家樂壞了!員工們齊心協力按要求準備好了 正準備派送時,突然碰到乙個棘手的問題,筷子!cx小朋友找出了餐廳中所有的筷子,但遺憾的是這些筷子長短不一,而我們都知道筷子需要長度一樣的才能組成一雙,更麻煩的是...

洛谷p1469 找筷子

題目介紹 經過一段時間的緊張籌備,電腦小組的 rp餐廳 終於開業了,這天,經理lxc接到了乙個定餐大單,可把大家樂壞了!員工們齊心協力按要求準備好了 正準備派送時,突然碰到乙個棘手的問題,筷子!cx小朋友找出了餐廳中所有的筷子,但遺憾的是這些筷子長短不一,而我們都知道筷子需要長度一樣的才能組成一雙,...