https://www.lydsy.com/JudgeOnline/problem.php?id=3653

https://www.luogu.org/problemnew/show/P3899

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

看到这题第一反应:woc点分治裸题233。

写了一回:woc点分治怎么写???

所以这就是为什么用主席树的原因了(并不

前两个条件只要固定了a和b我们就知道c的方案一定是a(或b,取决于谁深度大)的子树大小-1.

事实上对于一个节点,它周围可以谈笑风生的节点要么是它的祖先要么是它子树的点。

对于前者,处理dep数组之后就很好解决了。

对于后者,dfs序更新节点再树上主席树维护dep数组记录每个节点的子树大小-1(前缀和)。

查询的时候就是正常的主席树了。

PS:1.5h debug结果:思维定式,结果把主席树建成了和以前树上主席树一样的树就gg,错误请看代码。

#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=3e5+;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct node{
int to,nxt;
}e[N*];
struct tree{
int l,r;
ll sum;
}tr[N*];
int cnt,n,q,head[N],sz[N],dep[N];
int rt[N],idx[N],tot,pool,maxd;
inline void add(int u,int v){
e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
}
void insert(int y,int &x,int l,int r,int p,ll w){
tr[x=++pool]=tr[y];
tr[x].sum+=w;
if(l==r)return;
int mid=(l+r)>>;
if(p<=mid)insert(tr[y].l,tr[x].l,l,mid,p,w);
else insert(tr[y].r,tr[x].r,mid+,r,p,w);
}
ll query(int y,int x,int l,int r,int l1,int r1){
if(r1<l||r<l1)return ;
if(l1<=l&&r<=r1)return tr[x].sum-tr[y].sum;
int mid=(l+r)>>;
return query(tr[y].l,tr[x].l,l,mid,l1,r1)+
query(tr[y].r,tr[x].r,mid+,r,l1,r1);
}
void dfs1(int u,int f,int d){
idx[u]=++tot;
sz[u]=;dep[u]=d;
maxd=max(maxd,d);
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==f)continue;
dfs1(v,u,d+);
sz[u]+=sz[v];
}
}
void dfs2(int u,int f){
insert(rt[idx[u]-],rt[idx[u]],,maxd,dep[u],sz[u]-);
//错误点,曾经写成insert(rt[idx[f]],rt[idx[u]],1,maxd,dep[u],sz[u]-1);
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==f)continue;
dfs2(v,u);
}
}
int main(){
n=read(),q=read();
for(int i=;i<n;i++){
int u=read(),v=read();
add(u,v);add(v,u);
}
dfs1(,,);dfs2(,);
for(int i=;i<=q;i++){
int p=read(),k=read();
ll ans=(ll)(sz[p]-)*min(dep[p]-,k);
ans+=query(rt[idx[p]-],rt[idx[p]+sz[p]-],,maxd,dep[p]+,dep[p]+k);
printf("%lld\n",ans);
}
return ;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

最新文章

  1. 玩儿转物联网IoT - 在Beagle Bone Black上运行node.js 程序
  2. x265,帧内预测代码分析
  3. OPNET下 op_pk_copy()的时间问题
  4. &amp;nbsp;兼容性问题
  5. JQ实现右下角scrollTop()事件
  6. cookie&amp;&amp;session再理解笔记
  7. 快速排序C++
  8. System.ArgumentOutOfRangeException: 指定的参数已超出有效值的范围
  9. OpenRisc-67-OR的汇编
  10. nginx 调优
  11. linux驱动(一)
  12. 2010 A B 2011 A B
  13. Talking Ben App砸壳记
  14. jsp发布后应用根目录
  15. int与integer的区别(基本数据类型与引用数据类型)
  16. 【Spark篇】--Spark中Standalone的两种提交模式
  17. web3js 进行转账
  18. javaWeb-Servlet工作原理
  19. django之组件
  20. JAVA基础中的注意点(一)

热门文章

  1. 图片文件转换成Base64编码实现ajax提交图片
  2. 探索 Flask
  3. hdu1045Fire Net(经典dfs)
  4. HDU - 6441(费马大定理)
  5. [Clr via C#读书笔记]Cp3共享程序集和强命名程
  6. DataTable转Json,Json转DataTable
  7. Kali渗透测试-SNMP
  8. HADOOP docker(十):hdfs 结构体系
  9. 嵌入式码农的10年Bug调试经验,值得一看
  10. “Hello World!”团队第三周召开的第五次会议