zoukankan      html  css  js  c++  java
  • CF804D Expected diameter of a tree 树的直径 根号分治

    LINK:Expected diameter of a tree

    1e5 带根号log 竟然能跑过!

    容易想到每次连接两个联通快 快速求出直径 其实是 (max(D1,D2,f_x+f_y+1)) 其中(D1,D2)分别为两个联通块内的直径.

    (f_x)表示 从x出发的最长链.

    这样容易想到 枚举一个块的点 然后其实要找到 (C=max(D1,D2)) 第一个位置满足(>C-f_x-1) 然后就能统计答案了.

    排序后扫描 复杂度要高 不如排序后二分.

    然后加一个记忆化就过了.

    原因是 这样其实本质上是一个根号分治.

    对于每次询问的两个块(x,y)如果有一个块小于(sqrt n) 那么复杂度为(sqrt n cdot logn)

    如果两个块同时大于(sqrt n) 那么显然对于每个大于(sqrt n)的集合都有(sqrt n)次这样的询问.

    求和可以得到复杂度还是为(nsqrt n cdot logn) 至此可以通过此题.

    code
    //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<ctime>
    #include<cctype>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 1000000001
    #define ldb long double
    #define pb push_back
    #define put_(x) printf("%d ",x);
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define gi(x) scanf("%lf",&x)
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define fep(n,p,i) for(RE int i=n;i>=p;--i)
    #define vep(p,n,i) for(RE int i=p;i<n;++i)
    #define pii pair<int,int>
    #define mk make_pair
    #define RE register
    #define P 1000000007ll
    #define gf(x) scanf("%lf",&x)
    #define pf(x) ((x)*(x))
    #define uint unsigned long long
    #define ui unsigned
    #define EPS 1e-4
    #define sq sqrt
    #define S second
    #define F first
    using namespace std;
    char *fs,*ft,buf[1<<15];
    inline char gc()
    {
    	return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
    	RE int x=0,f=1;RE char ch=gc();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    	return x*f;
    
    }
    const int MAXN=100010;
    int n,m,Q,cnt,top,mx;
    vector<ll>G[MAXN],c[MAXN];
    int g[MAXN],f[MAXN],w[MAXN],s[MAXN],id[MAXN],vis[MAXN];
    int lin[MAXN],ver[MAXN<<1],nex[MAXN<<1],len;
    map<int,ll>H[MAXN];
    inline void add(int x,int y)
    {
    	ver[++len]=y;nex[len]=lin[x];lin[x]=len;
    	ver[++len]=x;nex[len]=lin[y];lin[y]=len;
    }
    inline void dfs(int x,int fa)
    {
    	vis[x]=cnt;
    	go(x)if(tn!=fa)
    	{
    		dfs(tn,x);
    		mx=max(mx,f[x]+f[tn]+1);
    		if(f[tn]+1>f[x])
    		{
    			g[x]=f[x];
    			f[x]=f[tn]+1;
    			id[x]=tn;
    		}
    		else g[x]=max(g[x],f[tn]+1);
    	}
    }
    inline void dp(int x,int fa)
    {
    	s[++top]=f[x];
    	go(x)if(tn!=fa)
    	{
    		if(id[x]!=tn)
    		{
    			if(f[x]+1>f[tn])
    			{
    				g[tn]=f[tn];
    				f[tn]=f[x]+1;
    				id[tn]=x;
    			}
    			else g[tn]=max(g[tn],f[x]+1);
    		}
    		else
    		{
    			if(g[x]+1>f[tn])
    			{
    				g[tn]=f[tn];
    				f[tn]=g[x]+1;
    				id[tn]=x;
    			}
    			else g[tn]=max(g[tn],g[x]+1);
    		}
    		dp(tn,x);
    	}
    }
    inline int find(int x,int y)
    {
    	
    	int l=0,r=G[x].size()-1;
    	while(l+1<r)
    	{
    		int mid=(l+r)>>1;
    		if(c[x][mid]<=y)l=mid;
    		else r=mid;
    	}
    	if(c[x][r]<=y)return r;
    	return l;
    }
    inline ll calc(int x,int y)
    {
    	if(H[x].find(y)!=H[x].end())return H[x][y];
    	int cc=max(w[x],w[y]);
    	ll ans=0;
    	vep(0,G[x].size(),i)
    	{
    		if(c[y][0]>cc-c[x][i]-1)
    		{
    			ans+=(ll)(1+c[x][i])*G[y].size()+G[y][G[y].size()-1];
    			continue;
    		}
    		if(c[y][c[y].size()-1]<=cc-c[x][i]-1)
    		{
    			ans+=(ll)G[y].size()*cc;
    			continue;
    		}
    		int ww=find(y,cc-c[x][i]-1);
    		ans+=(ll)(ww+1)*cc+G[y][G[y].size()-1]-G[y][ww]+(1+c[x][i])*(G[y].size()-ww-1);
    	}
    	H[x][y]=ans;return ans;
    }
    int main()
    {
    	//freopen("1.in","r",stdin);
    	get(n);get(m);get(Q);
    	rep(1,m,i)add(read(),read());
    	rep(1,n,i)
    	{
    		if(vis[i])continue;
    		mx=top=0;++cnt;dfs(i,0);dp(i,0);
    		sort(s+1,s+1+top);w[cnt]=mx;
    		rep(1,top,j)G[cnt].pb(s[j]),c[cnt].pb(s[j]);
    		rep(1,top-1,j)G[cnt][j]+=G[cnt][j-1];
    	}
    	rep(1,Q,i)
    	{
    		int get(x),get(y);
    		if(vis[x]==vis[y]){puts("-1");continue;}
    		x=vis[x];y=vis[y];
    		if(G[x].size()>G[y].size())swap(x,y);
    		if(G[x].size()==G[y].size()&&x>y)swap(x,y);
    		printf("%.7lf
    ",1.0*calc(x,y)/(G[x].size()*G[y].size()));
    	}
    	return 0;
    }
    
  • 相关阅读:
    基数排序
    计数排序和桶排序
    部署Java Web项目到云服务器的步骤全解析
    IP地址0.0.0.0/0是什么意思
    Tomcat在阿里云Centos7上正常启动,但浏览器无法访问的解决方法
    eclipse光标怎么返回上一次浏览的位置
    IDEA设置方法自动显示参数提示
    socket通信模型、socket中的accept()阻塞与read()阻塞
    Ubuntu18.04 下修改 root密码
    Ubuntu18.04 安装 VMwareTools
  • 原文地址:https://www.cnblogs.com/chdy/p/13357367.html
Copyright © 2011-2022 走看看