题解 P1232 【[NOI2013]树的计数】
[NOI2013]树的计数
目前讲的最清楚的solution?(大雾)
Click here for a better reading experience(人话:myblog)
给定树的
为了方便,对编号做修改(不影响答案)。
每个
①只能分段,
②分不分都行,
③不能分,
对于②、③,我们用一个差分数组
累计
至于①,我们可以直接处理掉,下面会讲
注意,对于根节点
有个问题,
观察发现,假设我们将
因为在同一层内,
所以
于是得出一个约束条件:
接下来考虑
还是考虑
发现它们之间有3种关系(红点为
1.
2.
3.
发现第3种情况有点东西:
然鹅怎么把第1,2种情况筛掉呢
发现对于第1种,
对于第2种,
(或者第3种的一层只有
再注意一些小细节(见code)于是就可以搞定这个思维题辣
参考博客:①,②
#include<iostream>
#include<cstdio>
#define rint register int
using namespace std;
#define N 200005
int read(){
char c=getchar();int x=0;
while(c<'0'||c>'9') c=getchar();
while('0'<=c&&c<='9') x=x*10+(c^48),c=getchar();
return x;
}
int n,s[N],b[N],d[N],a[N],c[N];
double ans;
int main(){
n=read(); ans=2; ++s[1];--s[2];//ans=2:根节点算1层+最下面的1层=2层
for(rint i=1;i<=n;++i) a[d[i]=read()]=i;
for(rint i=1;i<=n;++i) c[b[i]=read()]=i;
for(rint i=1;i<=n;++i) d[i]=c[d[i]],b[i]=a[b[i]];
for(rint i=1;i<n;++i) if(b[i]>b[i+1]) ++s[i],--s[i+1],++ans;//ans没有算到最下面的一层,先加上去
for(rint i=1;i<n;++i) if(d[i]+1<d[i+1]) ++s[d[i]],--s[d[i+1]];
for(rint i=1,w=0;i<n;++i) w+=s[i],ans+=w?0:0.5;//第n个点后面都是空的给它分段有什么意义吗
// printf("%.3f\n%.3f\n%.3f",ans-0.001,ans,ans+0.001);
// bzoj需要输出以上ans-0.001,ans,ans+0.001(大雾)
printf("%.3f",ans);
return 0;
}