題目描述
這個遊戲會給出你一棵樹,這棵樹有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小朋友找出了餐廳中所有的筷子,但遺憾的是這些筷子長短不一,而我們都知道筷子需要長度一樣的才能組成一雙,...