题面:P3899 [湖南集训]谈笑风生

题解:

我很喜欢这道题。

因为A是给定的,所以实质是求二元组的个数。我们以A(即给定的P)作为基点寻找答案,那么情况分两类。一种是B为A的父亲,另一种是A为B的父亲。

第一种情况很好处理,写法见代码,懒得讲,反正很简单的。

第二种情况的话,按Dfs序建主席树,用主席树维护下标为Dep的序列,每次用Size-1(因为不能取本身;Size[i]即为以i为根的子树节点数)去更新,

询问的时候在以A为根的子树中查找Dep[A]+1~Dep[A]+K的和即可。

不思考自然是看不懂的。

代码:

 #include<cstdio>
#include<cstring>
#include<iostream>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
inline ll rd(){
ll x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return f*x;
}
const int maxn=(3e5)+,maxq=(3e5)+;
int N,Q,num_edge=,edge_head[maxn],U,V,Le[maxn],Ri[maxn],P,root[maxn],num_treenode=,maxdep;
int Dfn[maxn],num_dfn=;
struct Edge{int to,nx;}edge[maxn<<];
ll Dep[maxn],Size[maxn],K,w,ans;
inline void Add_edge(int from,int to){
edge[++num_edge].nx=edge_head[from];
edge[num_edge].to=to;
edge_head[from]=num_edge;
return;
}
struct Tree{int l,r,ls,rs;ll sum;}t[(maxn<<)+(maxn*)];
inline void Build(int x,int l,int r){//建以深度为下标的主席树
t[x].l=l;t[x].r=r;int mid=(l+r)>>;
if(l==r)return;
Build(t[x].ls=++num_treenode,l,mid);
Build(t[x].rs=++num_treenode,mid+,r);
return;
}
inline void Dfs(int x,int fa){
Dfn[++num_dfn]=x;
Le[x]=num_dfn;
Dep[x]=Dep[fa]+;
maxdep=max(maxdep,Dep[x]);
Size[x]=;
for(int i=edge_head[x];i;i=edge[i].nx){
int y=edge[i].to;
if(y!=fa){
Dfs(y,x);
Size[x]+=Size[y];
}
}
Ri[x]=num_dfn;
return;
}
inline void Update(int u,int x,int q,int s){
int l=t[u].l,r=t[u].r,mid=(l+r)>>;
t[x].l=l;t[x].r=r;
if(l==r&&l==q){t[x].sum=t[u].sum+s; return;}
if(q<=mid){
t[x].rs=t[u].rs;
Update(t[u].ls,t[x].ls=++num_treenode,q,s);
}
else{
t[x].ls=t[u].ls;
Update(t[u].rs,t[x].rs=++num_treenode,q,s);
}
t[x].sum=t[t[x].ls].sum+t[t[x].rs].sum;
return;
}
inline void Query(int u,int x,int ql,int qr){
int l=t[u].l,r=t[u].r,mid=(l+r)>>;
if(ql<=l&&r<=qr){
ans=ans+t[x].sum-t[u].sum;
return;
}
if(ql<=mid)Query(t[u].ls,t[x].ls,ql,qr);
if(qr>mid) Query(t[u].rs,t[x].rs,ql,qr);
return;
}
int main(){
N=rd();Q=rd();
for(int i=;i<N;i++){
U=rd();V=rd();
Add_edge(U,V);
Add_edge(V,U);
}
Dep[]=-;//由于我的写法的原因,把根节点的深度设为0
Dfs(,);
Build(root[]=++num_treenode,,maxdep+);
Dfn[]=;
for(int i=;i<=num_dfn;i++)
Update(root[Dfn[i-]],root[Dfn[i]]=++num_treenode,Dep[Dfn[i]],Size[Dfn[i]]-);
while(Q--){
P=rd();K=rd();
ans=;
//先往父亲找
if(Dep[P]>=K)w=K;else w=Dep[P];
ans+=w*(Size[P]-);
//往儿子找
Query(root[P],root[Dfn[Ri[P]]],Dep[P]+,Dep[P]+K);
printf("%lld\n",ans);
}
return ;
}

By:AlenaNuna

主席树 || 可持久化线段树 || BZOJ 3653: 谈笑风生 || Luogu P3899 [湖南集训]谈笑风生的更多相关文章

  1. luogu P3899 [湖南集训]谈笑风生 线段树合并

    Code: #include<bits/stdc++.h> #define maxn 300002 #define ll long long using namespace std; vo ...

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

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

  3. 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex

    题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...

  4. [BZOJ 4771]七彩树(可持久化线段树+树上差分)

    [BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...

  5. 归并树 划分树 可持久化线段树(主席树) 入门题 hdu 2665

    如果题目给出1e5的数据范围,,以前只会用n*log(n)的方法去想 今天学了一下两三种n*n*log(n)的数据结构 他们就是大名鼎鼎的 归并树 划分树 主席树,,,, 首先来说两个问题,,区间第k ...

  6. 主席树[可持久化线段树](hdu 2665 Kth number、SP 10628 Count on a tree、ZOJ 2112 Dynamic Rankings、codeforces 813E Army Creation、codeforces960F:Pathwalks )

    在今天三黑(恶意评分刷上去的那种)两紫的智推中,突然出现了P3834 [模板]可持久化线段树 1(主席树)就突然有了不详的预感2333 果然...然后我gg了!被大佬虐了! hdu 2665 Kth ...

  7. BZOJ.4771.七彩树(可持久化线段树)

    BZOJ 考虑没有深度限制,对整棵子树询问怎么做. 对于同种颜色中DFS序相邻的两个点\(u,v\),在\(dfn[u],dfn[v]\)处分别\(+1\),\(dfn[LCA(u,v)]\)处\(- ...

  8. 权值线段树&&可持久化线段树&&主席树

    权值线段树 顾名思义,就是以权值为下标建立的线段树. 现在让我们来考虑考虑上面那句话的产生的三个小问题: 1. 如果说权值作为下标了,那这颗线段树里存什么呢? ----- 这颗线段树中, 记录每个值出 ...

  9. BZOJ 3483 SGU505 Prefixes and suffixes(字典树+可持久化线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3483 [题目大意] 给出一些串,同时给出m对前缀后缀,询问有多少串满足给出的前缀后缀模 ...

随机推荐

  1. ionic ion-tab图标修改, 自定义tab图标

    遇到需要自定义tab图标很简单, 只需要自定义相应的css就可以了, 这里要注意的是如何调整背景图片的大小. <ion-view hide-back-button="false&quo ...

  2. ionic andorid apk 签名, 查看签名MD5

    ionic cordova build android生成的是带签名的android-debug.apk, 这个是可以在手机上安装的, 但是换个电脑打包这个签名就不一样了, 这样就不能直接替换安装了, ...

  3. 【PMP】项目管理ITTO概述

    1.项目整合管理

  4. 在Ubuntu18.04下配置HBase

    HBase在HDFS基础上提供了高可靠, 列存储, 可扩展的数据库系统. HBase仅能通过主键(row key)和主键的range来检索数据, 主要用来存储非结构化和半结构化的松散数据. 与Hado ...

  5. 生产环境CPU过高问题定位

    问题描述:       生产环境下的某台tomcat7服务器,在刚发布时的时候一切都很正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高. 解决过程: 1.根据top命令,发现 ...

  6. 爬虫破解js加密(一) 有道词典js加密参数 sign破解

    在爬虫过程中,经常给服务器造成压力(比如耗尽CPU,内存,带宽等),为了减少不必要的访问(比如爬虫),网页开发者就发明了反爬虫技术. 常见的反爬虫技术有封ip,user_agent,字体库,js加密, ...

  7. vue的js文件中获取vue实例

    1.main.js导出vue实例: var vue = new Vue({ el: '#app', router, components: { App }, template: '<App/&g ...

  8. Replication基础(六) 复制中的三个线程(IO/SQL/Dump)

    Reference:  https://blog.csdn.net/sun_ashe/article/details/82181811?utm_source=blogxgwz1 简介在MySQL复制技 ...

  9. 凭什么相信你,我的CNN模型

    背景 学术界一直困惑的点是"如何让看似黑盒的CNN模型说话",即对它的分类结果给出解释. 这里的解释是指,让模型告诉我们它是通过图片的哪些像素做出判断的,并不是深度学习理论层面的解 ...

  10. virtualbox 在物理机是无线网卡的时候做桥接配置

    在“计算机”图标上右键选择“管理”,在打开的“计算机管理”窗口中选择左侧的“设备管理器”,然后在右侧图示的地方右键选择“添加过时硬件”. 在打开的窗口中点击“下一步”. 选择“安装我手动从列表中选择的 ...