1 条题解

  • 0
    @ 2022-6-8 9:17:07
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=2e6+7;
    int n;
    double ans;
    int dfn[N],pos[N],sum[N];//sum是差分数组
    //dfn是节点的dfs序,pos是dfn的反数组,所以有 pos[dfn[i]]=i,dfn[pos[i]]=i
    inline void mark(int x,int y) { sum[x]++,sum[y+1]--; }//打差分标记
    int main()
    {
    	// freopen("1.in","r",stdin);
    	n=read();
    	ans=1; mark(1,1);//第一个节点一定要分一层
    	for(int i=1;i<=n;i++) dfn[read()]=i;//读入初始dfs序
    	for(int i=1;i<=n;i++) pos[dfn[read()]]=i;//用初始dfs序更新变化后的pos
    	//上面一行不太好想。因为bfs序重标号了,原来的节点read()就变成了i,所以pos[dfn[read()]]=i
    	for(int i=1;i<=n;i++) dfn[pos[i]]=i;//用更新后的pos更新dfn
    	for(int i=1;i<n;i++)//注意i不取n
    	{
    		if(dfn[i]>dfn[i+1]) ans++,mark(i,i);//注意这里也要打标记,之后不会再产生0.5的贡献
    		if(pos[i]<pos[i+1]-1) mark(pos[i],pos[i+1]-1);//打标记
    	}
    	int now=0;
    	for(int i=1;i<n;i++) now+=sum[i],ans+=(now ? 0 : 0.5);//如果这个位置不确定则贡献为0.5
    	//注意上一行i不取n,因为切的位置只有n-1个
    	ans+=1;//深度等于分的段数+1
    	// printf("%.3lf\n%.3lf\n%.3lf",ans-0.001,ans,ans+0.001);//BZOJ上要这样输出...
    	printf("%.3lf\n",ans);
    	return 0;
    }
    
    • 1

    信息

    ID
    233
    时间
    1000ms
    内存
    125MiB
    难度
    6
    标签
    递交数
    2
    已通过
    2
    上传者