题目链接

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

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

思路

三个点肯定在1到c的链上

a已经确定

1.b是a的祖先,答案就是(siz[u]-1)*min(dis[u]-1,k)

2.a是b的祖先,要求\(1<=dis[b]-dis[a]<=k\)

\(1+dis[a]<=dis[b]<=k+dis[a]\)

第一问可以快速求出

第二问无脑线段树合并

代码

#include <bits/stdc++.h>
#define ll long long
#define it_ll vector<ll>::iterator
#define it_pair vector<pair<ll,ll> >::iterator
using namespace std;
const ll N=3e5+7;
ll read() {
ll x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
ll n,m,dis[N],siz[N];
vector<pair<ll,ll> > Q[N];
vector<ll> G[N];
void dfs(ll u,ll f) {
dis[u]=dis[f]+1;
siz[u]=1;
for(it_ll it=G[u].begin();it!=G[u].end();++it) {
if(*it==f) continue;
dfs(*it,u);
siz[u]+=siz[*it];
}
}
namespace seg {
struct node {
ll ls,rs,tot;
}e[N*30];
ll cnt;
void insert(ll &rt,ll l,ll r,ll id,ll k) {
if(!rt) rt=++cnt;
e[rt].tot+=k;
if(l==r) return;
ll mid=(l+r)>>1;
if(id<=mid) insert(e[rt].ls,l,mid,id,k);
else insert(e[rt].rs,mid+1,r,id,k);
}
ll query(ll rt,ll l,ll r,ll L,ll R) {
if(L<=l&&r<=R) return e[rt].tot;
ll mid=(l+r)>>1;
if(L<=mid&&R>mid) return query(e[rt].ls,l,mid,L,R)+query(e[rt].rs,mid+1,r,L,R);
if(L<=mid) return query(e[rt].ls,l,mid,L,R);
if(R>mid) return query(e[rt].rs,mid+1,r,L,R);
}
ll merge(ll x,ll y){
if(!x||!y) return x+y;
e[x].tot+=e[y].tot;
e[x].ls=merge(e[x].ls,e[y].ls);
e[x].rs=merge(e[x].rs,e[y].rs);
return x;
}
}
ll rt[N];
ll ans[N];
ll solve(ll u,ll f) {
seg::insert(rt[u],1,n,dis[u],siz[u]-1);
for(it_ll it=G[u].begin();it!=G[u].end();++it) {
if(*it==f) continue;
solve(*it,u);
rt[u]=seg::merge(rt[u],rt[*it]);
}
for(it_pair it=Q[u].begin();it!=Q[u].end();++it) {
ans[it->second]=1LL*seg::query(rt[u],1,n,dis[u]+1,dis[u]+it->first)+1LL*(siz[u]-1)*min(dis[u]-1,it->first);
// cout<<seg::e[seg::e[rt[u]].rs].tot<<" ["<<dis[u]+1<<", "<<dis[u]+it->first<<"]\n";
// cout<<1LL*seg::query(rt[u],1,n,dis[u]+1,dis[u]+it->first)<<"\n";
}
}
int main() {
n=read(),m=read();
for(ll i=1;i<n;++i) {
ll x=read(),y=read();
G[x].push_back(y),G[y].push_back(x);
}
for(ll i=1;i<=m;++i) {
ll p=read(),k=read();
Q[p].push_back(make_pair(k,i));
}
dfs(1,0);
solve(1,0);
for(ll i=1;i<=m;++i) printf("%lld\n",ans[i]);
return 0;
}

P3899 [湖南集训]谈笑风生的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. 【洛谷 P3899】 [湖南集训]谈笑风生 (主席树)

    题目链接 容易发现\(a,b,c\)肯定是在一条直链上的. 定义\(size(u)\)表示以\(u\)为根的子树大小(不包括\(u\)) 分两种情况, 1.\(b\)是\(a\)的祖先,对答案的贡献是 ...

  8. bzoj 3653 [湖南集训]谈笑风生

    题目描述 设 T 为一棵有根树,我们做如下的定义: • 设 a 和 b 为 T 中的两个不同节点.如果 a 是 b 的祖先,那么称"a 比 b 不知道高明到哪里去了". • 设 a ...

  9. Luogu 3899 [湖南集训]谈笑风生

    BZOJ 3653权限题. 这题方法很多,但我会的不多…… 给定了$a$,我们考虑讨论$b$的位置: 1.$b$在$a$到根的链上,那么这样子$a$的子树中的每一个结点(除了$a$之外)都是可以成为$ ...

随机推荐

  1. 如何使用Apache log4net库与ASP.NET MVC 5日志记录

    在运行软件程序的时候,跟踪和监控日志是一种记录过程的好方法. 简介: 在运行软件程序的时候,跟踪和监控日志是一种记录过程的好方法.尤其在应用程序出错的时候,日志是我们最需要的文件.不管是在web,wi ...

  2. CRUD简单查询

    一.查询所有数据 select * from car 二.查询指定列 select code , price from car 三.修改查询出的列名 select code as '代号' , nam ...

  3. uvm设计分析——tlm

    tlm模块,用来在不同模块之间实现实时通信,主要基于两个定义在通信双方的port类来实现. 两个port之间,通过connect函数,来拿到双方的class指针,进而调用对方的function. 但是 ...

  4. 强化学习--Policy Gradient

    Policy Gradient综述: Policy Gradient,通过学习当前环境,直接给出要输出的动作的概率值.   Policy Gradient  不是单步更新,只能等玩完一个epoch,再 ...

  5. Shader1.0学习笔记之SetTexture

    1.语法 SetTexture [TextureName] {Texture Block} 2.Texture block combine 命令 combine src1 *  src2 越乘越暗 c ...

  6. Spark学习之路 (十七)Spark分区

    一.分区的概念 分区是RDD内部并行计算的一个计算单元,RDD的数据集在逻辑上被划分为多个分片,每一个分片称为分区,分区的格式决定了并行计算的粒度,而每个分区的数值计算都是在一个任务中进行的,因此任务 ...

  7. MapReduce的map个数调节 与 Hadoop的FileInputFormat的任务切分原理

    在对日志等大表数据进行处理的时候需要人为地设置任务的map数,防止因map数过小导致集群资源被耗光.可根据大表的数据量大小设置每个split的大小. 例如设置每个split为500M: set map ...

  8. python中的作用域以及内置函数globals()-全局变量、locals()-局部变量

    在python中,函数会创建一个自己的作用域,也称为为命名空间.这意味着在函数内部访问某个变量时,函数会优先在自己的命名空间中寻找. 通过内置函数globals()返回的是python解释器能知道的变 ...

  9. Python读写docx文件

    Python读写word文档有现成的库可以处理.我这里采用 python-docx.可以用pip install python-docx安装一下. 这里说一句,ppt和excel也有类似的库哦,而且是 ...

  10. 查看gc的次数

    1,查找出程序进程id # 这里输出tomcat的进程id echo `ps -ef|grep tomcat|grep -v 'grep'|awk '{print $2'}` 2,查看gc的次数 js ...