题面: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. Docker CE 镜像源站

    sudo apt-get update sudo apt-get -y install apt-transport-https ca-certificates curl software-proper ...

  2. Python禁用GC优化性能

    Python使用的(Garbage Collection, GC)机制是引用计数(Reference Count),其原理是为每一个内存对象进行引用计数,因此当有大量的对象新建或删除时,必须要进行大量 ...

  3. Linear SVM和LR的区别和联系

    首先,SVM和LR(Logistic Regression)都是分类算法.SVM通常有4个核函数,其中一个是线性核,当使用线性核时,SVM就是Linear SVM,其实就是一个线性分类器,而LR也是一 ...

  4. Java驱动远程连接mongoDB(简明易懂版)

    mongodb默认是不能远程连接的,而且在linux安装完你会发现,它的目录极其简单,连个配置文件都没有. 我的mongodb的版本是3.6,目前最新的.https://www.mongodb.com ...

  5. LVS简介与使用

    一.LVS是什么? LVS的英文全称是Linux Virtual Server,即Linux虚拟服务器.它是我们国家的章文嵩博士的一个开源项目.在linux内存2.6中,它已经成为内核的一部分,在此之 ...

  6. C#学习笔记(34)——委托传值(回忆版)

    说明(2018-4-6 20:31:03): 1. 昨天晚上看三层,看完第一天的最后一节,会员的修改和增加,感觉欲仙欲死,果断关机睡觉. 2. 上午搞了半天哈利波特的原版书epub的下载,结果都没发现 ...

  7. iOS- UITextView与键盘回收与键盘遮挡输入框

    一.UITextView 可以实现多行输入的文本框,基本属性与UITextField相似,可以输入多行,可以滚动.UITextView还有个代理方式- (BOOL)textView:(UITextVi ...

  8. idea系列ide给git增加push按钮

    第一步 打开设置 Appearance & Behavior -- Menus and ToolBars,选中VscNavBarToolBarActios,然后点击"+"添 ...

  9. 【iCore4 双核心板_FPGA】实验十九:使用JTAT UART终端打印信息

    实验指导书及源代码下载地址: 链接:https://pan.baidu.com/s/1c3mqDkW 密码:4x9h iCore4链接:

  10. Java自定义注解的使用

    什么是注解? #============================================================================================ ...