[NOI2013] 树的计数
这题不太会。
看题解才大概懂的。
考虑期望的线性性
如果点对 \((x,y)\) 必须处在不同层,那么期望 \(+1\) , 必须在相同层则没有贡献
如果不确定是否在同层,则为\(0.5\)
1.如果两个点在 \(bfs\) 序中相邻, \(BFS[a] < BFS[b]\) ,且满足 \(DFS[a] > DFS[b]\) ,那么就必须不同层
2.如果两个点在 \(dfs\) 序中相邻, \(DFS[a] < DFS[b]\) ,且满足 \(BFS[a] > BFS[b]\) ,代表这两个点的深度差不超过 1,就意味着 \(BFS\) 序中,\(a 到 b\) 之间的点必须同层
[NOI2013] 树的计数
#include <iostream>
#include <cstdio>
#define MAXX 200005
using namespace std;
struct Nice {
int a , b , c , p , s , t;
}g[MAXX];
int n;
double Ans;
void Read() {
scanf("%d",&n);
for (int i=1 , x; i<=n; i++) {
scanf("%d",&x);
g[x].p = i;
}
for (int i=1 , x; i<=n; i++) {
scanf("%d",&x);
g[g[x].p ].a = i;
g[i].b = g[x].p ;
}
}
void Work() {
g[1].t ++;
g[1].c ++;
g[2].c --;
for (int i=2; i<=n; i++) {
if (g[i].b > g[i + 1].b ) {
g[i].t ++;
g[i].c ++;
g[i + 1].c --;
}
}
for (int i=1; i<=n; i++) {
g[i].s = g[i - 1].s + g[i].t ;
}
for (int i=1; i<=n; i++) {
if (g[i].a < g[i + 1].a && g[g[i + 1].a - 1].s - g[g[i].a - 1].s ) {
g[g[i].a ].c ++;
g[g[i + 1].a ].c --;
}
}
}
int main() {
Read();
Work();
for (int i=1; i<=n; i++) {
g[i].c += g[i - 1].c ;
if (g[i].c ) Ans += g[i].t ;
else Ans += 0.5;
}
printf("%.3lf",Ans);
}