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 行,每行对应一个询问,代表询问的答案。

题解:对于第二种情况,直接用子树大小计算一下就行了.

对于第三种情况,用树上线段树合并,计算出每个点所维护的深度的线段树就行了.

至于怎么计算,用线段树合并即可.

  1. #include<bits/stdc++.h>
  2. #define maxn 300002
  3. #define ll long long
  4. using namespace std;
  5. void setIO(string s)
  6. {
  7. string in=s+".in";
  8. string out=s+".out";
  9. freopen(in.c_str(),"r",stdin);
  10. freopen(out.c_str(),"w",stdout);
  11. }
  12. namespace tr
  13. {
  14. #define lson t[x].l
  15. #define rson t[x].r
  16. #define mid ((l+r)>>1)
  17. int cnt;
  18. int newnode(){ return ++cnt; }
  19. struct Node
  20. {
  21. int l,r;
  22. ll val, sumv;
  23. }t[maxn*60];
  24. void insert(int &x,int l,int r,int k,ll delta)
  25. {
  26. if(!x) x = newnode();
  27. t[x].sumv += delta;
  28. if(l==r) { t[x].val=delta; return; }
  29. if(k <= mid) insert(lson, l, mid, k, delta);
  30. else insert(rson, mid + 1, r, k, delta);
  31. }
  32. int merge(int u,int v)
  33. {
  34. if(!u||!v) return u + v;
  35. int x = newnode();
  36. t[x].sumv = t[u].sumv + t[v].sumv;
  37. lson = merge(t[u].l,t[v].l);
  38. rson = merge(t[u].r,t[v].r);
  39. return x;
  40. }
  41. ll query(int x,int l,int r,int L,int R)
  42. {
  43. if(!x) return 0;
  44. if(l>=L&&r<=R) return t[x].sumv;
  45. ll tmp=0;
  46. if(L<=mid) tmp+=query(lson,l,mid,L,R);
  47. if(R>mid) tmp+=query(rson,mid+1,r,L,R);
  48. return tmp;
  49. }
  50. };
  51. int n,Q,edges;
  52. int hd[maxn],to[maxn<<1],nex[maxn<<1],fa[maxn],siz[maxn],dep[maxn],rt[maxn];
  53. void add(int u,int v)
  54. {
  55. nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
  56. }
  57. void get(int u,int ff)
  58. {
  59. int i,v;
  60. siz[u]=1, dep[u] = dep[ff] + 1;
  61. for(i=hd[u];i;i=nex[i])
  62. {
  63. v=to[i];
  64. if(v==ff) continue;
  65. get(v,u), siz[u]+=siz[v];
  66. }
  67. }
  68. void DFS(int u,int ff)
  69. {
  70. int i,v;
  71. tr::insert(rt[u],0,n,dep[u],1ll*(siz[u]-1));
  72. for(i=hd[u];i;i=nex[i])
  73. {
  74. v=to[i];
  75. if(v==ff) continue;
  76. DFS(v, u);
  77. rt[u] = tr::merge(rt[v], rt[u]);
  78. }
  79. }
  80. int main()
  81. {
  82. // setIO("input");
  83. int i,j,x,y;
  84. ll ans=0;
  85. scanf("%d%d",&n,&Q);
  86. for(i=1;i<n;++i)
  87. {
  88. scanf("%d%d",&x,&y);
  89. add(x,y), add(y,x);
  90. }
  91. dep[0] = -1, get(1,0), DFS(1,0);
  92. while(Q--)
  93. {
  94. scanf("%d%d",&x,&y);
  95. ans = 0;
  96. ans += 1ll*(siz[x]-1) * min(dep[x] , y);
  97. ans += 1ll*tr::query(rt[x], 0, n, dep[x] + 1, dep[x] + y);
  98. printf("%lld\n",ans);
  99. }
  100. return 0;
  101. }

  

luogu P3899 [湖南集训]谈笑风生 线段树合并的更多相关文章

  1. 洛谷P3899 [湖南集训]谈笑风生(线段树合并)

    题意 题目链接 Sol 线段树合并板子题,目前我看到两种写法,分别是这样的. 前一种每次需要新建一个节点,空间是\(O(4nlogn)\) 后者不需要新建,空间是\(O(nlogn)\)(面向数据算空 ...

  2. [Luogu P3899] [湖南集训]谈笑风生 (主席树)

    题面 传送门:https://www.luogu.org/problemnew/show/P3899 Solution 你们搞的这道题啊,excited! 这题真的很有意思. 首先,我们可以先理解一下 ...

  3. 主席树 || 可持久化线段树 || BZOJ 3653: 谈笑风生 || Luogu P3899 [湖南集训]谈笑风生

    题面:P3899 [湖南集训]谈笑风生 题解: 我很喜欢这道题. 因为A是给定的,所以实质是求二元组的个数.我们以A(即给定的P)作为基点寻找答案,那么情况分两类.一种是B为A的父亲,另一种是A为B的 ...

  4. luogu P3899 [湖南集训]谈笑风生

    传送门 nmyzd,mgdhls,bnmbzdgdnlql,a,wgttxfs 对于一个点\(a\),点\(b\)只有可能是他的祖先或者在\(a\)子树里 如果点\(b\)是\(a\)祖先,那么答案为 ...

  5. P3899 [湖南集训]谈笑风生 主席树

    #include<iostream> #include<string.h> #include<algorithm> #include<stdio.h> ...

  6. P3899 [湖南集训]谈笑风生

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3653 https://www.luogu.org/problemnew/show/P38 ...

  7. 【Luogu】P3521ROT-Tree Rotations(线段树合并)

    题目链接 神奇的线段树合并qwq   不过就思路而言很好想…… 观察到一棵树无论怎么交换两棵左右子树,子树内部的最优逆序对并没影响……决策只影响左右子树之间的逆序对…… 于是线段树合并直接乱搞就好啦 ...

  8. luogu P4775 [NOI2018]情报中心 线段树合并 虚树 树的直径trick

    LINK:情报中心 神题! 写了一下午 写到肚子疼. 调了一晚上 调到ex 用的是网上dalao的方法 跑的挺快的. 对于链的暴力 我不太会kk. 直接说正解吧: 分类讨论两种情况: 1 答案的两条链 ...

  9. luogu P3180 [HAOI2016]地图 仙人掌 线段树合并 圆方树

    LINK:地图 考虑如果是一棵树怎么做 权值可以离散 那么可以直接利用dsu on tree+树状数组解决. 当然 也可以使用莫队 不过前缀和比较难以维护 外面套个树状数组又带了个log 套分块然后就 ...

随机推荐

  1. Mac下intellij idea环境的项目的新建、配色、快捷键的配置

    注:本文所使用的intellij idea是14.1.2的版本号. 一.项目的新建(以新建Java项目为例) 选中当中的"create new project". 接下来你会看到下 ...

  2. 2016/1/21 练习 创建 接口interface 应用implements 类class 并实例化调用

    package testinterface; public interface ICpu { //电压 public boolean dianya(); //控制 public void kongzh ...

  3. 【bzoj3676】[Apio2014]回文串 —— 回文自动机的学习

    写题遇上一棘手的题,[Apio2014]回文串,一眼看过后缀数组+Manacher.然后就码码码...过是过了,然后看一下[Status],怎么慢这么多,不服..然后就搜了一下,发现一种新东西——回文 ...

  4. GCD总结(一)

    GCD为我们提供了三种类型的调度队列(dispatch queue),分别为串行,并行和主调度队列. 串行(Serial)     你可以创建任意个数的串行队列,每个队列依次执行添加的任务,一个队列同 ...

  5. 洛谷P1155 双栈排序——思路题

    题目:https://www.luogu.org/problemnew/show/P1155 思路... 看博客:https://www.cnblogs.com/Narh/p/9213825.html ...

  6. bzoj2466

    高斯消元+搜索 很明显每个开关只能按一次,那么我们可以想到高斯消元,其实就是解异或方程组,但是最后会有一些自由元,也就是有x+y=z,x+y=z这种一样的方程就会产生自由元,那么我们爆搜自由元取值,每 ...

  7. FastDFS的介绍

    FastDFS的介绍 FastDFS FastDFS是由国人余庆所开发,其项目地址: https://github.com/happyfish100 FastDFS是一个轻量级的开源分布式文件系统,主 ...

  8. ubuntu 12.04不能mount nfs目录与挂载后只读不能写问题 (转载)

    转自:http://blog.chinaunix.net/uid-20680966-id-3810455.html 服务器用的是fedora 12  以前在helper2416开发板上挂载服务器上的n ...

  9. P3258[JLOI2014]松鼠的新家(LCA 树上差分)

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  10. 搞定springboot项目连接远程服务器上kafka遇到的坑以及完整的例子

    版本 springboot 2.1.5.RELEASE kafka 2.2 遇到的坑 用最新的springboot就要用最新的kafka版本! 当我启动云服务器上的zk后,再启动kafka后台日志也没 ...