[性质]luogu P1232 [NOI2013]树的计数

题面

https://www.luogu.com.cn/problem/P1232

分析

很神的一道思维题。

考虑把BFS序排序,那么分成多少段就是树的深度。

将DFS序投射到到BFS序上,x的DFS序大于x+1的,则必须在x,x+1之间分层,贡献固定为1

对DFS序排序讨论(BFS序要求递减),对于相邻的x,y:

1、x>y-1,此时可以发现y必然是x的祖先的儿子,无贡献

2、x=y-1,可构成兄弟或父子关系,贡献为0.5

3、x<y-1,可以发现该贡献已经在BFS序排序中计算了,不计算该贡献

对第三种情况用一个差分数组维护限制即可。

代码

#include <iostream>
#include <cstdio>
using namespace std;
const int N=2e5+10;
int n;
int dfn[N],bfn[N],c[N],ans;

int main() {
    scanf("%d",&n);ans=4;c[1]=1;c[2]=-1;
    for (int i=1,u;i<=n;i++) scanf("%d",&u),dfn[u]=i;
    for (int i=1,u;i<=n;i++) scanf("%d",&u),bfn[dfn[u]]=i;
    for (int i=1;i<=n;i++) dfn[bfn[i]]=i;
    for (int i=1;i<n;i++) {
        if (dfn[i]>dfn[i+1]) ans+=2,c[i]++,c[i+1]--;
        if (bfn[i]+1<bfn[i+1]) c[bfn[i]]++,c[bfn[i+1]]--;
    }
    for (int i=1;i<n;i++) c[i]+=c[i-1],ans+=(!c[i]);
    printf("%.3lf",(double)ans/2.0);
}
View Code
原文地址:https://www.cnblogs.com/mastervan/p/13854710.html