• BZOJ3653


    3653: 谈笑风生

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 1352  Solved: 588
    [Submit][Status][Discuss]

    Description

    设T 为一棵有根树,我们做如下的定义:
    ? 设a和b为T 中的两个不同节点。如果a是b的祖先,那么称“a比b不知道
    高明到哪里去了”。
    ? 设a 和 b 为 T 中的两个不同节点。如果 a 与 b 在树上的距离不超过某个给定
    常数x,那么称“a 与b 谈笑风生”。
    给定一棵n个节点的有根树T,节点的编号为1 到 n,根节点为1号节点。你需
    要回答q 个询问,询问给定两个整数p和k,问有多少个有序三元组(a;b;c)满足:
    1. a、b和 c为 T 中三个不同的点,且 a为p 号节点;
    2. a和b 都比 c不知道高明到哪里去了;
    3. a和b 谈笑风生。这里谈笑风生中的常数为给定的 k。

    Input

    第一行含有两个正整数n和q,分别代表有根树的点数与询问的个数。
    接下来n - 1行,每行描述一条树上的边。每行含有两个整数u和v,代表在节点u和v之间有一条边。
    接下来q行,每行描述一个操作。第i行含有两个整数,分别表示第i个询问的p和k。
    1<=P<=N
    1<=K<=N
    N<=300000
    Q<=300000

    Output

    输出 q 行,每行对应一个询问,代表询问的答案。

    Sample Input

    5 3
    1 2
    1 3
    2 4
    4 5
    2 2
    4 1
    2 3

    Sample Output

    3
    1
    3

    HINT

    Hint:边要加双向

    ___________________________________________________________

    DFS序+离线分层处理数据

    求书上符合条件的三元组(a,b,c)的数量。a为给定点,b点到a点的距离不超过一直量k,且a,b为祖孙的关系,c为a、b的子孙。

    根据a、b的关系分成两类:

    1、b为a的祖先。那么b的可能有min(k,dep[a]-1)种,而c的可能为siz[a]-1种,那么两个值的成绩就是答案。

    2、b为a的子孙,那么b的可能为所有与a深度差不超过k的子孙点,而c点的肯为对应每个b点的子孙树(siz[b]-1)

    第一种情况比较好求,深搜可以求出对应dep[]和siz[],然后乘起来就好了

    第二种情况比较麻烦,因为有多问,没问要遍历所有b的可能点,然后求对应c点的可能(siz[b]-1)之和。这个复杂度太高,不可完成。

    所以离线,把所有问题保存起来,其中每一问b点的最深深度是关键,用它对问题进行重新排序。这样一层一层的更新每个点的子孙数量(-1),用树状数组维护,但已经更新到当前这一问的最深深度时,用树状数组求出对应子树的和,就是答案。

    按照黄学长的说法,离线比较简单,但是我没有怎么学过离线的算法,所以理解了好一会儿,很巧妙!膜拜一下!

    ___________________________________________________________

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=3e5+10;
      4 int n,m;
      5 struct edge
      6 {
      7     int u,v,nxt;
      8 }e[maxn<<1];
      9 int head[maxn],js;
     10 void addage(int u,int v)
     11 {
     12     e[++js].u=u;e[js].v=v;
     13     e[js].nxt=head[u];head[u]=js;
     14 }
     15 int dep[maxn],lt[maxn],rt[maxn],cnt,siz[maxn],depf[maxn];
     16 void dfs(int u,int fa)
     17 {
     18     dep[u]=dep[fa]+1;
     19     lt[u]=++cnt;
     20     siz[u]=1;
     21     for(int i=head[u];i;i=e[i].nxt)
     22     {
     23         int v=e[i].v;
     24         if(v==fa)continue;
     25         dfs(v,u);
     26         depf[u]=max(depf[u],depf[v]);
     27         siz[u]+=siz[v];
     28     }
     29     depf[u]++;
     30     rt[u]=cnt;
     31 }
     32 int Q[maxn],t,h;
     33 void bfs()
     34 {
     35     h=0;
     36     Q[t=1]=1;
     37     while(t>h)
     38     {
     39         int u=Q[++h];
     40         for(int i=head[u];i;i=e[i].nxt)
     41         {
     42             int v=e[i].v;
     43             if(dep[v]<dep[u])continue;
     44             Q[++t]=v;
     45         }
     46     }
     47 }
     48 struct que
     49 {
     50     int p,k,dp,id;
     51     long long ans;
     52 }q[maxn];
     53 bool cmp(que a,que b)
     54 {
     55     return a.dp<b.dp;
     56 }
     57 long long da[maxn];
     58 long long sz[maxn];
     59 void change(int x,int y)
     60 {
     61     for(int i=x;i<=n;i+=i&(-i))sz[i]+=y;
     62 }
     63 long long query(int x)
     64 {
     65     long long ans=0;
     66     for(int i=x;i>0;i-=i&(-i))ans+=sz[i];
     67     return ans;
     68 }
     69 int main()
     70 {
     71     scanf("%d%d",&n,&m);
     72     for(int u,v,i=1;i<n;++i)
     73     {
     74         scanf("%d%d",&u,&v);
     75         addage(u,v);addage(v,u);
     76     }
     77     dfs(1,0);
     78     bfs();
     79     for(int i=1;i<=m;++i)
     80     {
     81         scanf("%d%d",&q[i].p,&q[i].k);
     82         q[i].dp=min(dep[q[i].p]+q[i].k,depf[q[i].p]+dep[q[i].p]-1);
     83         q[i].id=i;
     84         q[i].ans=1LL*min(dep[q[i].p]-1,q[i].k)*(siz[q[i].p]-1);
     85     }
     86     sort(q+1,q+1+m,cmp);
     87     int cur=1;
     88     for(int i=1;i<=m;++i)
     89     {
     90         int deep=q[i].dp;
     91         while(Q[cur]!=0 && dep[Q[cur]]<=deep)
     92         {
     93             change(lt[Q[cur]],siz[Q[cur]]-1);
     94             cur++;
     95         }
     96         q[i].ans+=query(rt[q[i].p])-query(lt[q[i].p]);
     97     }
     98     for(int i=1;i<=m;++i)da[q[i].id]=q[i].ans;
     99     for(int i=1;i<=m;++i)printf("%lld
    ",da[i]);
    100     return 0;
    101 }
    View Code
  • 相关阅读:
    0502-计算图
    0601-利用pytorch的nn工具箱实现LeNet网络
    0501-Variable
    0201-PyTorch0.4.0迁移指南以及代码兼容
    0401-Tensor的基础操作
    0303-利用手写数字问题引入深度神经网络
    0302-利用pytorch解决线性回归问题
    ZT台式机 Tensorflow配置
    java计算日期之间的时间差并转为毫秒
    sklearn cluster KMeans
  • 原文地址:https://www.cnblogs.com/gryzy/p/11797330.html
Copyright © 2020-2023  润新知