• codeforces 519E


    题意:

    给一棵树,每次询问给两个点u,v,求到这两个点距离相等的点的个数。(n,q<=1e5)

    题解:

    简单题,考虑u,v所在链,如果奇数条边显然ans=0;

        偶数条边则这两个点的中点x符合条件,考虑链外还有什么点符合条件:中点x连着的其他子树中的点;

        倍增+分类讨论一波;

    坑点:u==v时的情况

     1 #include<bits/stdc++.h>
     2 #define maxn 100005
     3 using namespace std;
     4 int n,q;
     5 struct edge
     6 {
     7     int to,next;
     8 }e[maxn<<1];
     9 int head[maxn],p;
    10 void addedge(int u,int v)
    11 {
    12     e[++p].to=v;e[p].next=head[u];head[u]=p;
    13 }
    14 int d[maxn],anc[maxn][20],size[maxn];
    15 void dfs(int u,int f)
    16 {
    17     size[u]=1;
    18     d[u]=d[f]+1;anc[u][0]=f;
    19     for(int i=head[u];i;i=e[i].next)
    20     {
    21         int v=e[i].to;
    22         if(v==f)continue;
    23         dfs(v,u);
    24         size[u]+=size[v];
    25     }
    26 }
    27 void predp()
    28 {
    29     for(int j=1;j<=18;++j)
    30         for(int i=1;i<=n;++i)anc[i][j]=anc[anc[i][j-1]][j-1];
    31 }
    32 int lca(int u,int v)
    33 {
    34     if(d[u]<d[v])swap(u,v);
    35     for(int i=18;i>=0;--i)if(d[anc[u][i]]>=d[v])u=anc[u][i];
    36     if(u==v)return u;
    37     for(int i=18;i>=0;--i)if(anc[u][i]!=anc[v][i])u=anc[u][i],v=anc[v][i];
    38     return anc[u][0];
    39 }
    40 int getanc(int x,int k)
    41 {
    42     for(int i=18;i>=0;--i)if(k>=(1<<i))x=anc[x][i],k-=(1<<i);
    43     return x;
    44 }
    45 int main()
    46 {
    47     scanf("%d",&n);
    48     for(int i=1;i<n;++i)
    49     {
    50         int u,v;
    51         scanf("%d%d",&u,&v);
    52         addedge(u,v);
    53         addedge(v,u);
    54     }
    55     dfs(1,0);
    56     predp();
    57     scanf("%d",&q);
    58     while(q--)
    59     {
    60         int u,v;
    61         scanf("%d%d",&u,&v);
    62         int t=lca(u,v);
    63         int dis1=d[u]-d[t],dis2=d[v]-d[t];
    64         int ans;
    65         if(u==v)ans=n;
    66         else if(dis1==dis2)
    67         {
    68             int x=getanc(u,dis1-1);
    69             int y=getanc(v,dis2-1);
    70             ans=n-size[x]-size[y];
    71         }
    72         else
    73         {
    74             if((dis1+dis2)&1)ans=0;
    75             else
    76             {
    77                 int D=(dis1+dis2)/2;
    78                 if(d[u]<d[v])swap(u,v);
    79                 int x=getanc(u,D);
    80                 int y=getanc(u,D-1);
    81                 ans=size[x]-size[y];
    82             }
    83         }
    84         printf("%d
    ",ans);
    85     }
    86     return 0;
    87 }
    View Code
  • 相关阅读:
    连分数与丢番图方程简介
    利用 random 与 tertools 模块解决概率问题
    Notepad++ 几款实用插件简介,让你的 Notepad++ 如虎添翼
    .net面试问答(大汇总)
    .net反射详解 原文://http://blog.csdn.net/wenyan07/article/details/27882363
    ASP.NET MVC4+EF5(Lambda/Linq)读取数据
    AngularJS+ASP.NET MVC+SignalR实现消息推送
    Asp.net SignalR 实现服务端消息推送到Web端
    C# Socket编程 同步以及异步通信
    C#版 Socket编程(最简单的Socket通信功能)
  • 原文地址:https://www.cnblogs.com/uuzlove/p/10447620.html
Copyright © 2020-2023  润新知