2211. 谈笑风生

★★★★   输入文件:laugh.in   输出文件:laugh.out   简单对比
时间限制:3 s   内存限制:512 MB

【问题描述】

设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 行,每行对应一个询问,代表询问的答案。

laugh.in

5 3

1 2

1 3

2 4

4 5

2 2

4 1

2 3

laugh.out

3

1

3

好题就要分享,若本题作者认为侵权,请告知我,我会尽快删除。

作者:TenderRun

  这道题目一看就是要用某种数据结构的。

  观察它的询问:有两类情况

    ①:b点是a点祖先,可以O(1)求出答案。

    ②:b是a子树中的一个节点,我们可以用DFS序,那么b点所在子树就是DFS序列中连续的一段,考虑对子树分层,接着用主席树水过了。

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int maxn=;
int cnt,fir[maxn],nxt[maxn<<],to[maxn<<];
void addedge(int a,int b){
nxt[++cnt]=fir[a];
fir[a]=cnt;
to[cnt]=b;
}
int dep[maxn],sz[maxn],ID[maxn],end[maxn],tot;
void DFS(int node){
sz[node]=;ID[node]=++tot;
for(int i=fir[node];i;i=nxt[i]){
if(dep[to[i]])continue;
dep[to[i]]=dep[node]+;
DFS(to[i]);
sz[node]+=sz[to[i]];
}
end[node]=tot;
}
queue<int>q;
int rt[maxn],ch[maxn*][],cont;
long long tr[maxn*];
void Insert(int pre,int &rt,int l,int r,int g){
rt=++cont;
ch[rt][]=ch[pre][];
ch[rt][]=ch[pre][];
tr[rt]=tr[pre]+sz[g]-;
if(l==r)return;
int mid=(l+r)>>;
if(ID[g]<=mid)Insert(ch[pre][],ch[rt][],l,mid,g);
else Insert(ch[pre][],ch[rt][],mid+,r,g);
}
long long Query(int pre,int rt,int l,int r,int a,int b){
if(l>=a&&r<=b)return tr[rt]-tr[pre];
int mid=(l+r)>>;
long long ret=;
if(mid>=a)ret=Query(ch[pre][],ch[rt][],l,mid,a,b);
if(mid<b)ret+=Query(ch[pre][],ch[rt][],mid+,r,a,b);
return ret;
}
int main(){
freopen("laugh.in","r",stdin);
freopen("laugh.out","w",stdout);
int n,Q;
scanf("%d%d",&n,&Q);
for(int i=,a,b;i<n;i++){
scanf("%d%d",&a,&b);
addedge(a,b);
addedge(b,a);
}
dep[]=;
DFS();
q.push();
int maxd=;
while(!q.empty()){
int node=q.front();q.pop();maxd=max(maxd,dep[node]);
if(!rt[dep[node]])Insert(rt[dep[node]-],rt[dep[node]],,n,node);
else Insert(rt[dep[node]],rt[dep[node]],,n,node);
for(int i=fir[node];i;i=nxt[i]){
if(dep[to[i]]!=dep[node]+)continue;
q.push(to[i]);
}
}
int a,k;
long long ans;
while(Q--){
scanf("%d%d",&a,&k);
ans=1ll*(min(k,dep[a]-))*(sz[a]-);
ans+=Query(rt[dep[a]],rt[min(dep[a]+k,maxd)],,n,ID[a],end[a]);
printf("%lld\n",ans);
}
return ;
}

数据结构(主席树):COGS 2211. 谈笑风生的更多相关文章

  1. 数据结构(主席树):COGS 2213. K个串

    2213. K个串 ★★★★   输入文件:bzoj_4504.in   输出文件:bzoj_4504.out   简单对比时间限制:20 s   内存限制:512 MB [题目描述] 兔子们在玩k个 ...

  2. 数据结构(主席树):HDU 5654 xiaoxin and his watermelon candy

    Problem Description During his six grade summer vacation, xiaoxin got lots of watermelon candies fro ...

  3. 【主席树】bzoj3653 谈笑风生

    设siz[i]表示i的子树大小-1. 询问中b在a上方的便于统计. 对于b在a下方的情况,贡献为距a距离在K以内的节点的siz之和. 按dfs序建立可持久化线段树,线段树的下标是深度. 相当于把每个点 ...

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

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

  5. COGS 2211. [BZOJ3653]谈笑风生

    ★★★★   输入文件:laugh.in   输出文件:laugh.out   简单对比时间限制:3 s   内存限制:512 MB [问题描述] 设T 为一棵有根树,我们做如下的定义: • 设a和b ...

  6. 刷题总结——谈笑风生(主席树+dfs序的应用)

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

  7. 【数据结构模版】可持久化线段树 && 主席树

    浙江集训Day4,从早8:00懵B到晚21:00,只搞懂了可持久化线段树以及主席树的板子.今天只能记个大概,以后详细完善讲解. 可持久化线段树指的是一种基于线段树的可回溯历史状态的数据结构.我们想要保 ...

  8. 数据结构(主席树):HZOI 2016 采花

    [题目描述] 给定一个长度为n,包含c种颜色的序列,有m个询问,每次给出两个数l,r,表示询问区间[l,r]中有多少种颜色的出现次数不少于2次. 本题强制在线,对输入的l,r进行了加密,解密方法为: ...

  9. 数据结构(主席树):HDU 4729 An Easy Problem for Elfness

    An Easy Problem for Elfness Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (J ...

随机推荐

  1. MAC 环境下 初始化新的mysql root 密码

    mac 环境下初始化mysql的root密码 关掉mysql服务,打开系统设置最后的mysql,然后将mysql先关掉 生成一个文件命名mysql-init,文件中放入:一句话,这句话不同版本不一样, ...

  2. ASP.NET中如何生成图形验证码

    通常生成一个图形验证码主要 有3个步骤: (1)随机产生一个长度为N的随机字符串,N的值可由开发可由开发人员自行设置.该字符串可以包含数字.字母等. (2)将随机生成的字符串创建成图片,并显示. (3 ...

  3. STM32串口通信USART1转USART2问题解决

    使用的是STM32f103ZET6. 1.把文件main.c和usart.c中的所有usart1换成usart2 2.查看手册得知USART2的引脚是Tx->PA2,Rx->PA3,改变u ...

  4. 关于get和set访问器以及属性和字段变量的区别问题

    属性是对一个或者多个字段的封装.      类里面为什么要用一个共有的属性来封装其中的字段,也可以这样说用共有属性来封装私有变量,其中的好处应该大家都说的出来,就是为了实现数据的封装和保证了数据的安全 ...

  5. 常用的dos命令之简略总结

    Dos常用命令  一.基础命令  1 dir  无参数:查看当前所在目录的文件和文件夹.  /s:查看当前目录已经其所有子目录的文件和文件夹.  /a:查看包括隐含文件的所有文件.  /ah:只显示出 ...

  6. CoreBluetooth

    Core Bluetooth的基本常识 每个蓝牙4.0设备都是通过服务(Service)和特征(Characteristic)来展示自己的 一个设备必然包含一个或多个服务,每个服务下面又包含若干个特征 ...

  7. JS 通过系统时间限定 动态添加 select option

    虽然是个简单的效果,还是需要积累一下,记录一下: 在八月一号之后,删除最后一项,新添加2016级 — — 2015级 2014级 2013级 2012级 在六月一号之后,删除最后一项,新添加2016级 ...

  8. JSP标准标签库的安装以及自定义标签的创建

    JSTL 库安装 Apache Tomcat安装JSTL 库步骤如下: 从Apache的标准标签库中下载的二进包(jakarta-taglibs-standard-current.zip). 官方下载 ...

  9. 启动scala的方法

    1.从官网 http://www.scala-lang.org/download/ 下载scala二进制通用版本以后,在终端命令行添加下载解压包的bin目录到环境变量: export PATH=/Us ...

  10. SGU 196.Matrix Multiplication

    时间限制:0.25s 空间限制:4M Solution n=10000,m=100000,显然不能用矩阵乘法乘出来. S= ATA 对于矩阵S的一行,所有在A矩阵中1位置的元素都相等,并且都等于这一行 ...