zoukankan      html  css  js  c++  java
  • 联考20200618 T2 分岔路口

    题目:

    分析:
    神仙期望,神仙结论:
    对于一个点,肯定先随机跳再一路走到终点,这样是最优的
    一个点向终点走了之后再随机跳,不会比直接随机跳更优
    一个点的期望只与他到终点的距离有关
    我们想找到一个阈值(D),使得离终点小于等于(D)的点直接走最优
    显然可以二分,可是如何判断?
    我们算出距离大于(mid)的点随机跳到小于等于(mid)的点的期望步数,加上直接走的期望步数(x)
    如果小于(mid)说明还要多进行随机跳,将(mid)缩小,否则增大
    期望步数(x)实际上是距离和除以点数,这个需要动态点分治维护一下
    复杂度(O(nlog^{2}n))

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    
    #define maxn 400005
    #define MOD 998244353
    #define INF 0x3f3f3f3f
    
    using namespace std;
    
    inline int getint()
    {
    	int num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int n,q;
    int fir[maxn],nxt[maxn],to[maxn],cnt;
    int f[18][maxn],dpt[maxn];
    int Sz[maxn],Dpt[maxn],Fa[maxn],vis[maxn];
    
    int dis[18][maxn];
    vector<long long>sz[maxn],fsz[maxn],sum[maxn],fsum[maxn];
    
    inline void newnode(int u,int v)
    {to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
    inline void getsz(int u,int lst,int N,int &mn,int &rt)
    {
    	Sz[u]=1;int mx=0;
    	for(int i=fir[u];i;i=nxt[i])if(!vis[to[i]]&&to[i]!=lst)
    	{
    		getsz(to[i],u,N,mn,rt),Sz[u]+=Sz[to[i]];
    		mx=max(mx,Sz[to[i]]);
    	}
    	mx=max(mx,N-Sz[u]);
    	if(mx<mn)mn=mx,rt=u;
    }
    inline int getrt(int u,int N)
    {
    	int mn=INF,rt;
    	getsz(u,0,N,mn,rt);return rt;
    }
    
    inline void getp(int u,int lst,int d,vector<long long>&sz,vector<long long>&sum)
    {
    	while(d>=sz.size())sz.push_back(0);
    	while(d>=sum.size())sum.push_back(0);
    	sz[d]++,sum[d]+=d,Sz[u]=1;
    	for(int i=fir[u];i;i=nxt[i])if(to[i]!=lst&&!vis[to[i]])
    		getp(to[i],u,d+1,sz,sum),Sz[u]+=Sz[to[i]]; 
    }
    inline void getdis(int u,int lst,int d,int id)
    {
    	dis[id][u]=d;
    	for(int i=fir[u];i;i=nxt[i])if(to[i]!=lst&&!vis[to[i]])
    		getdis(to[i],u,d+1,id);
    }
    
    inline void solve(int u,int d)
    {
    	vis[u]=1,Dpt[u]=d;
    	getp(u,0,0,sz[u],sum[u]);
    	getdis(u,0,0,d);
    	for(int i=1;i<sz[u].size();i++)
    		sz[u][i]+=sz[u][i-1],sum[u][i]+=sum[u][i-1];
    	for(int i=fir[u];i;i=nxt[i])if(!vis[to[i]])
    	{
    		int t=getrt(to[i],Sz[to[i]]);
    		Fa[t]=u;
    		getp(to[i],0,1,fsz[t],fsum[t]);
    		for(int i=1;i<fsz[t].size();i++)
    			fsz[t][i]+=fsz[t][i-1],fsum[t][i]+=fsum[t][i-1];
    		solve(t,d+1);
    	}
    }
    
    inline void dfs(int u)
    {
    	for(int i=fir[u];i;i=nxt[i])if(to[i]!=f[0][u])
    		f[0][to[i]]=u,dpt[to[i]]=dpt[u]+1,dfs(to[i]);
    }
    inline int LCA(int u,int v)
    {
    	if(dpt[u]<dpt[v])swap(u,v);
    	for(int i=17;~i;i--)if((dpt[u]-dpt[v])&(1<<i))u=f[i][u];
    	if(u==v)return u;
    	for(int i=17;~i;i--)if(f[i][u]!=f[i][v])u=f[i][u],v=f[i][v];
    	return f[0][u];
    }
    
    inline pair<long long,long long>query(int p,int x)
    {
    	long long ret1=0,ret2=0;
    	int u=p,pr=0;
    	while(p)
    	{
    		if(x-dis[Dpt[p]][u]>=0)
    		{
    			int t=x-dis[Dpt[p]][u];
    			ret1+=sz[p][min((int)sz[p].size()-1,t)];
    			ret2+=sum[p][min((int)sum[p].size()-1,t)]+sz[p][min((int)sz[p].size()-1,t)]*dis[Dpt[p]][u];
    			if(pr)
    			{
    				ret1-=fsz[pr][min((int)fsz[pr].size()-1,t)];
    				ret2-=fsum[pr][min((int)fsum[pr].size()-1,t)]+fsz[pr][min((int)fsz[pr].size()-1,t)]*dis[Dpt[p]][u];
    			}
    		}
    		pr=p,p=Fa[p];
    	}
    	return make_pair(ret1,ret2);
    }
    
    int main()
    {
    	n=getint(),q=getint();
    	for(int i=1;i<n;i++)
    	{
    		int u=getint(),v=getint();
    		newnode(u,v),newnode(v,u);
    	}
    	solve(getrt(1,n),0);
    	dfs(1);
    	for(int j=1;j<18;j++)for(int i=1;i<=n;i++)f[j][i]=f[j-1][f[j-1][i]];
    	while(q--)
    	{
    		int x=getint(),y=getint();
    		int L=0,R=n,mid;
    		while(L<R)
    		{
    			mid=(L+R+1)>>1;
    			pair<long long,long long>t=query(y,mid);
    			double g=1.0*(t.second+n-t.first)/t.first;
    			if(g+1<mid)R=mid-1;
    			else L=mid; 
    		}
    		pair<long long,long long>t=query(y,L);
    		double g=1.0*(t.second+n-t.first)/t.first;
    		printf("%.8lf
    ",min(g+1,1.0*dpt[x]+dpt[y]-2*dpt[LCA(x,y)]));
    	}
    }
    

  • 相关阅读:
    SpringCloud微服务初步认识
    SpringCloud-Hystrix:服务熔断与降级
    List接口下重要集合源码分析
    高频面试题:手写一个LRU
    Java基础面试题面经整理(持续更新)
    Redis高可用之主从复制
    Redis过期键删除和内存淘汰
    Redis持久化(RDB与AOF)
    了解Redis事务
    Redis入门与安装
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13160516.html
Copyright © 2011-2022 走看看