题目描述

设 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 。

输入格式

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

输出格式

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

样例输入

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

样例输出



3

题目分析

下图是样例数据:

  对于询问2 2, b可以取1或4

  •   b取1时, c可以取4, 5:

ans += 1 * 2

  • b取4时, c只能取5:

ans += 1 * 1

  • 综上ans = 3
  • 可以发现对于询问a,k: 若根节点的dep为0, sze[i]表示以i为根的树的大小
  1. b可以在根节点到a的路径上,此时c可以是a子树中的任意节点 ans += min(dep[a], k) * (sze[a] - 1)
  2. b可以是a的子树节点中且与a的距离小于等于k, 对于每一个b, c可以是b子树结点中的任意一点

$$ans += \sum_{b} sze[b] - 1$$

  • 由此, 先dfs出树的dep,sze

  然后需要加上a子树结点中与a距离小于等于k的节点的子树大小之和.

  • 我们可以使用可持久化线段树来完成这一任务。我们对深度建线段树,按照 DFS 序的
    顺序依次插入每个点。这样就可以通过全部的测试点。
  • 具体可以看代码;

CODE:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<string>
  6. #include<cmath>
  7. #include<algorithm>
  8. using namespace std;
  9.  
  10. typedef long long ll;
  11. const int N = ;
  12. int n, q;
  13. #define bug(x) cout<<#x<<":"<<x<<endl
  14.  
  15. inline int Re(){
  16. int i = , f = ; char ch = getchar();
  17. for(; (ch < '' || ch > '') && ch != '-'; ch = getchar());
  18. if(ch == '-') f = -, ch = getchar();
  19. for(; ch >= '' && ch <= ''; ch = getchar())
  20. i = (i << ) + (i << ) + (ch - '');
  21. return i * f;
  22. }
  23.  
  24. struct node{
  25. int lc, rc;
  26. ll sum;
  27. }tr[N << ];
  28. int pool, root[N], sze[N], dep[N], in[N], out[N], id;
  29.  
  30. int ecnt, adj[N], go[N << ], nxt[N << ], maxx, pos[N];
  31.  
  32. inline void Insert(const int &x, int &y, const int &l, const int &r, const int &pos, const int &v){
  33. tr[y = ++pool] = tr[x];
  34. tr[y].sum += v;
  35. if(l == r) return;
  36. int mid = l + r >> ;
  37. if(pos <= mid) Insert(tr[x].lc, tr[y].lc, l, mid, pos, v);
  38. else Insert(tr[x].rc, tr[y].rc, mid + , r, pos, v);
  39. }
  40.  
  41. inline ll query(int pos, const int &nl, const int &nr, const int &l, const int &r){
  42. if(l <= nl && nr <= r) return tr[pos].sum;
  43. int mid = nl + nr >> ;
  44. ll ret = ;
  45. if(l <= mid) ret += query(tr[pos].lc, nl, mid, l, r);
  46. if(r > mid ) ret += query(tr[pos].rc, mid + , nr, l, r);
  47. return ret;
  48. }
  49.  
  50. inline void addEdge(const int &u, const int &v){
  51. nxt[++ecnt] = adj[u], adj[u] = ecnt, go[ecnt] = v;
  52. nxt[++ecnt] = adj[v], adj[v] = ecnt, go[ecnt] = u;
  53. }
  54.  
  55. inline void dfs(const int &u, const int &f){
  56. dep[u] = dep[f] + ;
  57. maxx = max(maxx, dep[u]);
  58. sze[u] = ;
  59. in[u] = ++id;
  60. pos[id] = u;
  61. int v;
  62. for(int e = adj[u]; e; e = nxt[e]){
  63. if((v = go[e]) == f) continue;
  64. dfs(v, u);
  65. sze[u] += sze[v];
  66. }
  67. out[u] = id;
  68. }
  69.  
  70. inline void tree_init(){
  71. for(int i = ; i <= n; i++){
  72. Insert(root[i - ], root[i], , maxx, dep[pos[i]], sze[pos[i]] - );
  73. }
  74. }
  75.  
  76. int main(){
  77. freopen("h.in", "r", stdin);
  78. n = Re(), q = Re();
  79. for(int i = ; i < n; i++){
  80. int u = Re(), v = Re();
  81. addEdge(u, v);
  82. }
  83. maxx = -; dep[] = -;
  84. dfs(, );
  85. tree_init();
  86. // for(int i = 1; i <= n; i++) bug(i),bug(dep[pos[i]]);
  87. for(int i = ; i <= q; i++){
  88. int p = Re();
  89. int k = Re();
  90. ll ans = ;
  91. ans += (ll)(sze[p] - ) * (ll)min(dep[p], k);
  92. // bug(ans);
  93. ans += query(root[out[p]], , maxx, min(dep[p] + , maxx), min(dep[p] + k, maxx));
  94. // bug(ans); bug(query(root[out[p]], 1, maxx, min(dep[p] + 1, maxx), min(dep[p] + k, maxx)));
  95. ans -= query(root[in[p] - ], , maxx, min(dep[p] + , maxx), min(dep[p] + k, maxx));
  96. cout<<ans<<endl;
  97. }
  98. return ;
  99. }

【NOI模拟】谈笑风生(主席树)的更多相关文章

  1. bzoj 3653 谈笑风生——主席树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3653 原来一直想怎么线段树合并.可是不会把角标挪一位. 查询的其实是子树内一段深度的点的 s ...

  2. bzoj 3653 谈笑风生 —— 主席树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3653 对于一个 (a,b,c),分成 b 是 a 的祖先和 b 在 a 子树里两部分: 第一 ...

  3. [BZOJ3653]谈笑风生 主席树

    题面 这道题应该比较裸吧. \(a\),\(b\)都是\(c\)的祖先. 那么第一种情况是\(b\)是\(a\)的祖先,那么方案数就是\(\min\{dep[a]-1,k\}\cdot (num[a] ...

  4. BZOJ 3653: 谈笑风生(主席树)

    传送门 解题思路 首先对于一个\(a\)来说,要求\(b\)和\(c\),那么\(a,b,c\)一定在一条链上.把\(b\)分类讨论,如果\(b\)是\(a\)的祖宗,这个方案数就很好统计了,就是\( ...

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

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

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

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

  7. Newnode's NOI(P?)模拟赛 第三题 (主席树优化建图 + tarjan)

    题目/题解戳这里 这道题题目保证a,b,ca,b,ca,b,c各是一个排列-mdzz考场上想到正解但是没看到是排列,相等的情况想了半天-然后写了暴力60分走人- 由于两两间关系一定,那么就是一个竞赛图 ...

  8. 数据结构(主席树):COGS 2211. 谈笑风生

    2211. 谈笑风生 ★★★★   输入文件:laugh.in   输出文件:laugh.out   简单对比时间限制:3 s   内存限制:512 MB [问题描述] 设T 为一棵有根树,我们做如下 ...

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

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

随机推荐

  1. 导入java项目时出现红色叹号问题的解决

    问题:导入java项目时出现红色叹号(如下图所示) 原因:引入项目的某些jar包跟自己电脑上的位置不一样: 解决方案:步骤如下 (1)右键红色叹号所在项目————>build path————& ...

  2. Maven基本安装与配置

    百度Maven,进入Maven官网,点击Download 点击下载Binary zip包,下载到电脑上相应的位置即可. 找到下载文件,进行解压,解压到相应的文件夹下面,并且记住路径. 打开系统-> ...

  3. 关于Dubbo分布式服务

    这篇文章写的详细,可参考 http://shiyanjun.cn/archives/1075.html

  4. 常见web容器

    当前主流的还是tomcat,jetty有较大的潜力,缩小彼此间差距,

  5. PHP验证码的制作教程

    自己过去自学了PHP绘画验证码的教程,现在就把这一部分笔记跟大家分享,希望可以帮到大家. 顺带,我会在后面把我整理的一整套CSS3,PHP,MYSQL的开发的笔记打包放到百度云,有需要可以直接去百度云 ...

  6. Bash中的数学计算

    一.整数计算 1.整数 $delare -i num$num=5+5$echo $num10 $num="5 + 8"$echo $num13注意:算式中如果有空格,需要用引号引起 ...

  7. canvas学习总结三:绘制路径-线段

    Canvas绘图环境中有些属于立即绘制图形方法,有些绘图方法是基于路径的. 立即绘制图形方法仅有两个strokeRect(),fillRect(),虽然strokezText(),fillText() ...

  8. 蜘蛛大战之 站点LOGO(SEO)

    起因: 同事让我看 搜公司名称,百度第一位并没有出现公司网址,是别人的,然后我 惊奇的发现,站点logo 竟然 抓了张 无关紧要的图片,从此 变开始了 为期 10天+的战争: 经过: [2017-06 ...

  9. Windows Server AppFabric分布式缓存研究

    分享一则先前对Windows Server AppFabric分布式缓存的技术研究. 一. AppFabric 技术架构和原理 AppFabric与Memcached类似,采用C/S的模式,在 ser ...

  10. Volley源码分析一

    Volley源码分析 虽然在2017年,volley已经是一个逐渐被淘汰的框架,但其代码短小精悍,网络架构设计巧妙,还是有很多值得学习的地方. 第一篇文章,分析了请求队列的代码,请求队列也是我们使用V ...