zoukankan      html  css  js  c++  java
  • BZOJ3451: Tyvj1953 Normal

    题解:

    好神的一道题。蒟蒻只能膜拜题解。

    考虑a对b的贡献,如果a是a-b路径上第一个删除的点,那么给b贡献1。

    所以转化之后就是求sigma(1/dist(i,j)),orz!!!

    如果不是分母的话O(n)就可以搞,但是现在在分母上。。。

    考虑转化一下,求ret[i]表示距离为i的点对有多少对。我们发现只要求出ret数组,然后就可以回答了。

    如何求ret,我们用点分治。类似于RACE那道题。

    对于一颗子树,我们整个信息一块统计,让它和前面的所有做卷积,更新ret,然后再把这棵子树归入前面的信息内。

    代码:

      1 #include<cstdio>
      2 
      3 #include<cstdlib>
      4 
      5 #include<cmath>
      6 
      7 #include<cstring>
      8 
      9 #include<algorithm>
     10 
     11 #include<iostream>
     12 
     13 #include<vector>
     14 
     15 #include<map>
     16 
     17 #include<set>
     18 
     19 #include<queue>
     20 
     21 #include<string>
     22 
     23 #define inf 1000000000
     24 
     25 #define maxn 50000+5
     26 
     27 #define maxm 20000000+5
     28 
     29 #define eps 1e-10
     30 
     31 #define ll long long
     32 
     33 #define pa pair<int,int>
     34 
     35 #define for0(i,n) for(int i=0;i<=(n);i++)
     36 
     37 #define for1(i,n) for(int i=1;i<=(n);i++)
     38 
     39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     40 
     41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     42 #define for4(i,x) for(int i=head[x],y;i;i=e[i].next)
     43 
     44 #define mod 1000000007
     45 
     46 using namespace std;
     47 
     48 inline int read()
     49 
     50 {
     51 
     52     int x=0,f=1;char ch=getchar();
     53 
     54     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     55 
     56     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     57 
     58     return x*f;
     59 
     60 }
     61 int n,mx,m,len,cnt,sum,tot,rt,rev[maxn],head[maxn],d[maxn],f[maxn],s[maxn],g[maxn];
     62 bool del[maxn];
     63 ll ret[maxn];
     64 const double PI=acos(-1.0);
     65 struct cp
     66 {
     67     double x,y;
     68     cp operator +(cp b){return (cp){x+b.x,y+b.y};}
     69     cp operator -(cp b){return (cp){x-b.x,y-b.y};}
     70     cp operator *(cp b){return (cp){x*b.x-y*b.y,x*b.y+y*b.x};}
     71 };
     72 cp a[2*maxn],b[2*maxn],c[2*maxn],y[2*maxn];
     73 struct edge{int go,next;}e[2*maxn];
     74 inline void insert(int x,int y)
     75 {
     76     e[++tot]=(edge){y,head[x]};head[x]=tot;
     77     e[++tot]=(edge){x,head[y]};head[y]=tot;
     78 }
     79 inline void getrt(int x,int fa)
     80 {
     81     s[x]=1;f[x]=0;
     82     for4(i,x)if(!del[y=e[i].go]&&y!=fa)
     83     {
     84         getrt(y,x);
     85         s[x]+=s[y];
     86         f[x]=max(f[x],s[y]);
     87     }
     88     f[x]=max(f[x],sum-f[x]);
     89     if(f[x]<f[rt])rt=x;
     90 }
     91 inline void getdep(int x,int fa,int w)
     92 {
     93     if(w>mx)mx=w;
     94     d[++cnt]=w;
     95     for4(i,x)if(!del[y=e[i].go]&&y!=fa)getdep(y,x,w+1);
     96 }
     97 inline void get(int n)
     98 {
     99     n++;n=2*n-1;
    100     m=1,len=0;
    101     while(m<=n)m<<=1,len++;
    102     for0(i,m-1)
    103     {
    104         int x=i,y=0;
    105         for1(j,len)y<<=1,y|=x&1,x>>=1;
    106         rev[i]=y;
    107     }
    108 }
    109 inline void fft(cp *x,int n,int flag)
    110 {
    111     for0(i,n-1)y[rev[i]]=x[i];
    112     for0(i,n-1)x[i]=y[i];
    113     for(int m=2;m<=n;m<<=1)
    114     {
    115         cp wn=(cp){cos(2.0*PI*flag/m),sin(2.0*PI*flag/m)};
    116         for(int i=0;i<n;i+=m)
    117         {
    118             cp w=(cp){1,0};int mid=m>>1;
    119             for0(j,mid-1)
    120             {
    121                 cp u=x[i+j],v=x[i+j+mid]*w;
    122                 x[i+j]=u+v;x[i+j+mid]=u-v;
    123                 w=w*wn;
    124             }
    125         }
    126     }
    127     if(flag==-1)for0(i,n-1)x[i].x/=n;
    128 }
    129 inline void work(int x)
    130 {
    131     //cout<<"XXXXX"<<' '<<x<<' '<<"XXXX"<<endl;
    132     del[x]=1;mx=0;
    133     for4(i,x)if(!del[y=e[i].go])
    134     {
    135         cnt=0;
    136         getdep(y,x,1);get(mx);
    137         for0(j,m-1)a[j]=(cp){g[j],0},b[j]=(cp){0,0};
    138         for1(j,cnt)b[d[j]].x+=1,g[d[j]]++;
    139         //for0(j,m-1)cout<<j<<' '<<a[j].x<<' '<<b[j].x<<endl;
    140         fft(a,m,1);fft(b,m,1);
    141         for0(j,m-1)c[j]=a[j]*b[j];
    142         fft(c,m,-1);
    143         for0(j,m-1)ret[j]+=c[j].x+0.5;
    144         //for0(j,m-1)cout<<j<<' '<<c[j].x<<' '<<c[j].y<<endl;
    145     }
    146     for1(i,mx)ret[i]+=g[i],g[i]=0;
    147     for4(i,x)if(!del[y=e[i].go])
    148     {
    149         sum=s[y];rt=0;
    150         getrt(y,0);
    151         work(rt);
    152     }
    153 }    
    154 
    155 int main()
    156 
    157 {
    158 
    159     freopen("input.txt","r",stdin);
    160 
    161     freopen("output.txt","w",stdout);
    162 
    163     n=read();
    164     for1(i,n-1)insert(read()+1,read()+1);
    165     sum=n;f[rt=0]=inf;
    166     getrt(1,0);
    167     work(rt);
    168     double ans=0.0;
    169     for1(i,n)
    170     ans+=(double)ret[i]/(double)(i+1);//cout<<i<<' '<<ret[i]<<endl;
    171     printf("%.4f
    ",n+2*ans);
    172 
    173     return 0;
    174 
    175 }  
    View Code

    3451: Tyvj1953 Normal

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 125  Solved: 60
    [Submit][Status]

    Description

    某天WJMZBMR学习了一个神奇的算法:树的点分治!
    这个算法的核心是这样的:
    消耗时间=0
    Solve(树 a)
     消耗时间 += a 的 大小
     如果 a 中 只有 1 个点
      退出
     否则在a中选一个点x,在a中删除点x
     那么a变成了几个小一点的树,对每个小树递归调用Solve
    我们注意到的这个算法的时间复杂度跟选择的点x是密切相关的。
    如果x是树的重心,那么时间复杂度就是O(nlogn)
    但是由于WJMZBMR比较傻逼,他决定随机在a中选择一个点作为x!
    Sevenkplus告诉他这样做的最坏复杂度是O(n^2)
    但是WJMZBMR就是不信>_<。。。
    于是Sevenkplus花了几分钟写了一个程序证明了这一点。。。你也试试看吧^_^
    现在给你一颗树,你能告诉WJMZBMR他的傻逼算法需要的期望消耗时间吗?(消耗时间按在Solve里面的那个为标准)

    Input

    第一行一个整数n,表示树的大小
    接下来n-1行每行两个数a,b,表示a和b之间有一条边
    注意点是从0开始标号的

    Output

    一行一个浮点数表示答案
    四舍五入到小数点后4位
    如果害怕精度跪建议用long double或者extended

    Sample Input

    3
    0 1
    1 2

    Sample Output

    5.6667

    HINT

    n<=30000

    Source

  • 相关阅读:
    RocketMQ实战:生产环境中,autoCreateTopicEnable为什么不能设置为true
    x 的平方根--二分查找
    责任链模式--设计模式
    迭代器模式--设计模式
    组合模式--设计模式
    搜索旋转排序数组II
    搜索旋转排序数组--二分查找
    搜索插入位置--二分查找
    越狱详解与调试--逆向开发
    有序链表转换二叉搜索树--链表
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4172395.html
Copyright © 2011-2022 走看看