[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);
}
posted @ 2021-04-12 21:51  fhq_treap  阅读(64)  评论(0编辑  收藏  举报