BZOJ3244 Noi2013 樹的計數

2021-08-15 23:26:29 字數 1836 閱讀 9766

這題其實我還不是很懂為什麼滿足了這兩個性質就一定合法qaq

先將所有點按其bfs序重新標號

我們令dfn[i]表示i的dfs序,bfn[i]表示dfs序為i的點的bfs序

考慮怎麼計算答案,我們令dep[i]表示點i所在樹中的層數,那麼對dep[i]做個差分,a[i]=a[i]-a[i-1],a[1]=a[2]=1,那麼∑a

i ∑ai

的期望就是樹的期望高度

對於bfs序相鄰的點i,i+1,

若dfn[i]>dfn[i+1],他們之間肯定換層了,a[

i+1]

=1a [i

+1]=

1若dfn[i]< dfn[i+1],他們可以換層也可以不換,a[

i+1]

=12 a[i

+1]=

12

對於dfs序相鄰的點bfn[i],bfn[i+1]

因為顯然有dep[bfn[i+1]]<=dep[bfn[i]]+1,所以若bfn[i]< bfn[i+1],有限制∑b

fn[i

+1]i

=bfn

[i]+

1a[i

]<=

1 ∑i=

bfn[

i]+1

bfn[

i+1]

a[i]

<=

1注意那個1/2的期望要滿足限制

畫一下圖可以發現如果乙個有限制的區間裡面沒有強制為1的a[

i]a [i

],那就也不會有期望1/2的a[

i]a [i

],所以維護乙個字首和用來打標記,o(n)掃一下就行了

輸出很坑…坑在**見**…

code:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define ll long long

using

namespace

std;

const

int maxn = 210000;

int a[maxn],to[maxn];

int s[maxn],pre[maxn],fl[maxn];

int n;

int main()

for(int i=1;i<=n;i++) a[i]=to[a[i]];

for(int i=1;i<=n;i++) to[a[i]]=i;

s[1]=s[2]=2;

for(int i=3;i<=n;i++)

if(to[i]1]) s[i]=2;

for(int i=1;i<=n;i++) pre[i]=pre[i-1]+s[i];

for(int i=2;iif(a[i]1]&&pre[a[i+1]]-pre[a[i]])

fl[a[i]+1]++,fl[a[i+1]+1]--;

int cc=0,ans=0;

for(int i=1;i<=n;i++)

double re=ans/2.0;

printf("%.3lf\n%.3lf\n%.3lf\n",re-0.001,re,re+0.001);

return

0;}

BZOJ3244 NOI2013樹的計數

給定一棵 n n 200000 個節點的樹的 df s bf s 序,求所有滿足要求的樹的平均深度。考慮到 bf s 序的性質,bf s 在前的點的深度一定小於等於後面的點。所以我們考慮根據 bf s 序計算答案。首先根據 bf s 序給樹上的點重編號,按 bf s 序的先後編成 1,2,n 考慮相...

BZOJ3244 NOI2013 樹的計數

我們知道一棵有根樹可以進行深度優先遍歷 dfs 以及廣度優先遍歷 bfs 來生成這棵樹的dfs序以及bfs序。兩棵不同的樹的dfs序有可能相同,並且它們的bfs序也有可能相同,例如下面兩棵樹的dfs序都是1 2 4 5 3,bfs序都是1 2 3 4 5 現給定乙個dfs序和bfs序,我們想要知道,...

bzoj3244 Noi2013 樹的計數

我們知道一棵有根樹可以進行深度優先遍歷 dfs 以及廣度優先遍歷 bfs 來生成這棵樹的dfs序以及bfs序。兩棵不同的樹的dfs序有可能相同,並且它們的bfs序也有可能相同,例如下面兩棵樹的dfs序都是1 2 4 5 3,bfs序都是1 2 3 4 5 現給定乙個dfs序和bfs序,我們想要知道,...