【NOI2013】树的计数【树的遍历】【期望】
生活随笔
收集整理的這篇文章主要介紹了
【NOI2013】树的计数【树的遍历】【期望】
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
傳送門
題意:給定一棵nnn個點的樹的DFS和BFS序,求樹高期望。
n≤2e5n \leq 2e5n≤2e5
首先根據(jù)BFS序將樹點分層,一定切記先自己把樹點分層,這樣實際上是在排除一部分情況。
將每一層第一個點打標記,答案就是期望標記個數(shù)。
首先BFS序第一個和第二個一定有標記。
對于之后BFS序相鄰的兩個,如果后面的DFS序小于前面的,說明這里分了層,給后面打上標記。
還有一個限制,DFS序相鄰的兩個點,后面最多比前面深一層。所以用前面的標記算出層數(shù),如果后面大于前面,用差分實現(xiàn)區(qū)間修改為-1,表示一定沒有標記。
而剩下的點可分可不分,貢獻0.50.50.5
復雜度O(n)O(n)O(n)
#include <iostream> #include <cstdio> #include <cstring> #include <cctype> #define MAXN 200005 using namespace std; inline int read() {int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans; } int dfs[MAXN],bfs[MAXN],dfn[MAXN],bfn[MAXN]; int mark[MAXN],dep[MAXN],s[MAXN]; int main() {int n=read();for (int i=1;i<=n;i++) dfn[dfs[i]=read()]=i;for (int i=1;i<=n;i++) bfn[bfs[i]=read()]=i;dep[bfs[1]]=dep[bfs[2]]=mark[bfs[1]]=mark[bfs[2]]=1;for (int i=2;i<n;i++)if (dfn[bfs[i+1]]<dfn[bfs[i]])dep[bfs[i+1]]=mark[bfs[i+1]]=1;for (int i=1;i<=n;i++) cerr<<mark[i]<<endl; for (int i=1;i<=n;i++) dep[bfs[i]]+=dep[bfs[i-1]];for (int i=1;i<n;i++)if (dep[dfs[i]]<dep[dfs[i+1]])++s[bfn[dfs[i]]+1],--s[bfn[dfs[i+1]]+1];for (int i=1;i<=n;i++) cerr<<s[i]<<endl;for (int i=1;i<=n;i++)if ((s[i]+=s[i-1])>0&&!mark[bfs[i]])mark[bfs[i]]=-1;for (int i=1;i<=n;i++) cerr<<mark[i]<<endl;double ans=0;for (int i=1;i<=n;i++)if (mark[i]==1) ans+=1;else if (mark[i]==0) ans+=0.5;printf("%.3f",ans);return 0; }總結
以上是生活随笔為你收集整理的【NOI2013】树的计数【树的遍历】【期望】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OI训练记录
- 下一篇: 【NOI2013】快餐店【基环树】【树的