• (WC2018模拟十二)【FJOI2016集训Day7T2】点对游戏


    题解:

    还好。。。看懂题目就好做了。(Orzdyh)

    首先选择的点是等概率随机的,也就是说每种选择结果的概率都是一样的,所以选择一个点的时候已经选择的点不会有影响,那么就可以直接算出点对个数再求总体的期望。具体来说,每条边会在$inom{n-2}{lceilfrac{n}{3} ceil -1}$种情况中被选择(说不清楚,感性理解一下),再除以总的情况数$inom{n}{lceilfrac{n}{3} ceil}$即可,这一步可以约分,注意要对$nmod 3$的余数分类讨论。

    前面的部分是点分治经典应用,就不说了。我貌似写的很挫,第一次有三个点T了20ms,其他人一共就跑了20ms。。。第二次加了读入优化999ms过了。。。妙不可言

    代码:

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<cmath>
      6 #include<queue>
      7 #define inf 2147483647
      8 #define eps 1e-9
      9 using namespace std;
     10 typedef long long ll;
     11 struct edge{
     12     int v,next;
     13 }a[100001];
     14 int n,m,u,v,lk[11],anss[11],sum=0,S,rt,tot=0,cnt=0,head[50001],siz[50001],mx[50001],dis[50001];
     15 bool used[50001];
     16 double ans1,ans2;
     17 char buffer[1000010],*hd,*tl;
     18 inline char Getchar(){
     19     if(hd==tl){
     20         int len=fread(buffer,1,1000000,stdin);
     21         hd=buffer,tl=hd+len;
     22         if(hd==tl)
     23             return EOF;
     24     }
     25     return *hd++;
     26 }
     27 inline int rd(){
     28     register int x=0;
     29     char c;
     30     do c=Getchar();
     31     while(!isdigit(c));
     32     do{
     33         x=(x<<1)+(x<<3)+(c^48);
     34         c=Getchar();
     35     }while(isdigit(c));
     36     return x;
     37 }
     38 inline void add(int u,int v){
     39     a[++tot].v=v;
     40     a[tot].next=head[u];
     41     head[u]=tot;
     42 }
     43 inline void dfsrt(int u,int ff){
     44     siz[u]=1;
     45     mx[u]=0;
     46     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
     47         int v=a[tmp].v;
     48         if(v!=ff&&!used[v]){
     49             dfsrt(v,u);
     50             mx[u]=max(mx[u],siz[v]);
     51             siz[u]+=siz[v];
     52         }
     53     }
     54     mx[u]=max(mx[u],S-siz[u]);
     55     if(mx[u]<mx[rt])rt=u;
     56 }
     57 inline void getdis(int u,int fa,int ds){
     58     dis[++cnt]=ds;
     59     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
     60         int v=a[tmp].v;
     61         if(v!=fa&&!used[v])getdis(v,u,ds+1);
     62     }
     63 }
     64 inline int gao1(int l,int r,int k){
     65     int ret=-1;
     66     while(l<=r){
     67         int mid=(l+r)/2;
     68         if(dis[mid]==k)ret=mid,l=mid+1;
     69         else if(dis[mid]<k)l=mid+1;
     70         else r=mid-1;
     71     }
     72     return ret;
     73 }
     74 inline int gao2(int l,int r,int k){
     75     int ret=0;
     76     while(l<=r){
     77         int mid=(l+r)/2;
     78         if(dis[mid]==k)ret=mid,r=mid-1;
     79         else if(dis[mid]<k)l=mid+1;
     80         else r=mid-1;
     81     }
     82     return ret;
     83 }
     84 inline int calc(int u,int w,int K){
     85     cnt=0;
     86     getdis(u,0,w);
     87     sort(dis+1,dis+cnt+1);
     88     //for(int i=1;i<=cnt;i++)printf("%d ",dis[i]);
     89     //printf("
    ");
     90     int ret=0;
     91     for(int i=1;i<=cnt;i++){
     92         if(dis[i]*2>K)break;
     93         ret+=gao1(i,cnt,K-dis[i])-gao2(i,cnt,K-dis[i])+1;
     94     }
     95     return ret;
     96 }
     97 inline void divide(int u){
     98     used[u]=true;
     99     for(int i=1;i<=m;i++)anss[i]+=calc(u,0,lk[i]);
    100     for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
    101         int v=a[tmp].v;
    102         if(!used[v]){
    103             for(int i=1;i<=m;i++){
    104                 anss[i]-=calc(v,1,lk[i]);
    105             }
    106             S=siz[v],rt=0;
    107             dfsrt(v,0);
    108             divide(rt);
    109         }
    110     }
    111 }
    112 int main(){
    113     memset(head,-1,sizeof(head));
    114     memset(anss,0,sizeof(anss));
    115     //scanf("%d%d",&n,&m);
    116     n=rd(),m=rd();
    117     for(int i=1;i<=m;i++)lk[i]=rd();//scanf("%d",&lk[i]);
    118     for(int i=1;i<n;i++){
    119         //scanf("%d%d",&u,&v);
    120         u=rd();
    121         v=rd();
    122         add(u,v);
    123         add(v,u);
    124     }
    125     S=n,mx[rt=0]=2333333;
    126     dfsrt(1,0);
    127     divide(rt);
    128     //for(int i=1;i<=m;i++)printf("%d ",anss[i]);
    129     for(int i=1;i<=m;i++)sum+=anss[i];
    130     if(n%3==1||n%3==2){
    131         ans1=(double)((double)sum*(n/3)*(n/3+1))/(double)((double)n*(n-1));
    132         if(n%3==1)printf("%.2lf
    ",ans1);
    133         else printf("%.2lf
    %.2lf
    ",ans1,ans1);
    134     }
    135     ans2=(double)((double)sum*(n/3)*(n/3-1))/(double)((double)n*(n-1));
    136     if(n%3==0)printf("%.2lf
    %.2lf
    %.2lf",ans2,ans2,ans2);
    137     else if(n%3==1)printf("%.2lf
    %.2lf",ans2,ans2);
    138     else printf("%.2lf",ans2);
    139     return 0;
    140 }
  • 相关阅读:
    (4.25)Sqlserver中 登录用户只能看到自己拥有权限的库
    【查阅】mysql配置文件/参数文件重要参数笔录(my.cnf)
    【监控笔记】【2.5】DML(CDC)、DDL(DDL触发器)跟踪数据更改,数据库审计
    SQL Server 2008中的CDC(Change Data Capture)功能使用及释疑
    【监控笔记】【2.4】SQL Server中的 Ring Buffer 诊断各种系统资源压力情况
    【监控笔记】【2.3】扩展事件——慢查询SQL(执行超过3S的SQL)
    【监控笔记】【2.2】扩展事件——死锁监控
    最小配置启动SQL SERVER,更改SQL Server最大内存大小导致不能启动的解决方法
    【监控笔记】【2.1】扩展事件
    【扩展事件】跟踪超过3秒的SQL
  • 原文地址:https://www.cnblogs.com/dcdcbigbig/p/9762638.html
Copyright © 2020-2023  润新知