【BZOJ】【3653】谈笑风生
dfs序+可持久化线段树
好吧……是我too naive
这题……$$ans=min(dep[x],k)×(size[x]-1)+\sum_{y在x的子树中,且dis(x,y)<=k}(size[y]-1)$$
那么重点是后面sigma的部分,这里看到子树中信息的统计可以用dfs序……但是对子树中dep在某个范围内的点的size求和?
我们可以用权值线段树呀~dep做关键字,size的和是线段树上统计的额外信息,那么对整个dfs序做可持久化线段树就可以了……查询的时候就像普通线段树一样。
调了很久的一个地方……
F(i,,n) update(root[i]=root[i-],,n,dep[a[i]],sz[a[i]]-);
这一句中我一开始写成.......dep[a[x]],sz[a[x]]-1了!!
因为在dfs的过程中我是用x这个变量来表示某个节点的……然后这里顺着思路就写下来了……
你可能会说,为什么没有CE呢?那是因为我在读入边的时候声明了两个变量x,y……看代码上下文就知道了TAT
/**************************************************************
Problem: 3653
User: Tunix
Language: C++
Result: Accepted
Time:8964 ms
Memory:158752 kb
****************************************************************/ //Huce #1 D
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=3e5+,INF=~0u>>;
typedef long long LL;
/******************tamplate*********************/
int head[N],to[N<<],next[N<<],cnt;
void add(int x,int y){
to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt;
to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt;
}
int n,m,a[N],dep[N],sz[N],st[N],ed[N],root[N],tot,ct;
struct Tree{
int l,r; LL sum;
}t[N*];
#define mid (l+r>>1)
void update(int &o,int l,int r,int pos,int w){
t[++ct]=t[o], o=ct, t[o].sum+=w;
if (l==r) return;
if (pos<=mid) update(t[o].l,l,mid,pos,w);
else update(t[o].r,mid+,r,pos,w);
}
LL query(int i,int j,int l,int r,int ql,int qr){
if (ql<=l && qr>=r){
return t[j].sum-t[i].sum;
}else{
LL ans=;
if (ql<=mid) ans+=query(t[i].l,t[j].l,l,mid,ql,qr);
if (qr> mid) ans+=query(t[i].r,t[j].r,mid+,r,ql,qr);
return ans;
}
}
#undef mid
void dfs(int x){
a[st[x]=++tot]=x;
sz[x]=;
for(int i=head[x];i;i=next[i])
if (st[to[i]]==){
dep[to[i]]=dep[x]+;
dfs(to[i]);
sz[x]+=sz[to[i]];
}
ed[x]=tot;
} int main(){
#ifndef ONLINE_JUDGE
freopen("D.in","r",stdin);
freopen("D.out","w",stdout);
#endif
n=getint(); m=getint();
int x,y;
F(i,,n){
x=getint(); y=getint();
add(x,y);
}
dfs();
F(i,,n) update(root[i]=root[i-],,n,dep[a[i]],sz[a[i]]-);
F(i,,m){
x=getint(); y=getint();
LL ans=(LL)(sz[x]-)*min(dep[x],y);
ans+=query(root[st[x]-],root[ed[x]],,n,
dep[x]+,min(dep[x]+y,n));
printf("%lld\n",ans);
}
return ;
}
3653: 谈笑风生
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 225 Solved: 79
[Submit][Status][Discuss]
Description
设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。
Input
输入文件的第一行含有两个正整数n和q,分别代表有根树的点数与询问的个数。接下来n - 1行,每行描述一条树上的边。每行含有两个整数u和v,代表在节点u和v之间有一条边。
接下来q行,每行描述一个操作。第i行含有两个整数,分别表示第i个询问的p和k。
Output
输出 q 行,每行对应一个询问,代表询问的答案。
Sample Input
1 2
1 3
2 4
4 5
2 2
4 1
2 3
Sample Output
1
3
HINT
1<=P<=N
1<=K<=N
N<=300000
Q<=300000
Source
【BZOJ】【3653】谈笑风生的更多相关文章
- BZOJ 3653: 谈笑风生(离线, 长链剖分, 后缀和)
题意 给你一颗有 \(n\) 个点并且以 \(1\) 为根的树.共有 \(q\) 次询问,每次询问两个参数 \(p, k\) .询问有多少对点 \((p, a, b)\) 满足 \(p,a,b\) 为 ...
- BZOJ.3653.谈笑风生(长链剖分/线段树合并/树状数组)
BZOJ 洛谷 \(Description\) 给定一棵树,每次询问给定\(p,k\),求满足\(p,a\)都是\(b\)的祖先,且\(p,a\)距离不超过\(k\)的三元组\(p,a,b\)个数. ...
- 主席树 || 可持久化线段树 || BZOJ 3653: 谈笑风生 || Luogu P3899 [湖南集训]谈笑风生
题面:P3899 [湖南集训]谈笑风生 题解: 我很喜欢这道题. 因为A是给定的,所以实质是求二元组的个数.我们以A(即给定的P)作为基点寻找答案,那么情况分两类.一种是B为A的父亲,另一种是A为B的 ...
- 【刷题】BZOJ 3653 谈笑风生
Description 设T 为一棵有根树,我们做如下的定义: ? 设a和b为T 中的两个不同节点.如果a是b的祖先,那么称"a比b不知道 高明到哪里去了". ? 设a 和 b 为 ...
- bzoj 3653 谈笑风生——主席树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3653 原来一直想怎么线段树合并.可是不会把角标挪一位. 查询的其实是子树内一段深度的点的 s ...
- bzoj 3653 谈笑风生 —— 主席树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3653 对于一个 (a,b,c),分成 b 是 a 的祖先和 b 在 a 子树里两部分: 第一 ...
- BZOJ 3653 谈笑风生
ORZ blutrex...... 主席树. #include<iostream> #include<cstdio> #include<cstring> #incl ...
- BZOJ 3653: 谈笑风生(DFS序+可持久化线段树)
首先嘛,还是太弱了,想了好久QAQ 然后,这道题么,明显就是求sigma(size[x]) (x是y的儿子且层树小于k) 然后就可以发现:把前n个节点按深度建可持久化线段树,就能用前缀和维护了 其实不 ...
- bzoj 3653: 谈笑风生 可持久化线段树
题目大意 在一棵单位边权的有根树上支持询问: 给定a,k求满足下列条件的有序三元对的个数. a,b,c互不相同 a,b均为c的祖先 a,b树上距离<=k 题解 solution 1 首先我们知道 ...
- bzoj 3653: 谈笑风生【dfs序+主席树】
考虑b的两种情况,一种是p的祖先,这种点有min(k,de[p]-1)个,然后每个这种b都有si[p]-1个c点可选: 另一种是p的子孙,要求是在p的子树内且deep在de[p]+1~de[p]+k之 ...
随机推荐
- 常用网络命令(windows)
Ping命令的常用参数选项 ·ping IP –t 连续对IP地址执行Ping命令,直到被用户以Ctrl+C中断. ·ping IP -l 3000 指定Ping命令中的数据长度为3000字节,而 ...
- Dubbo的容错与负载均衡
虽然前面在介绍dubbo中写过这块内容,但是不够充分,这里详细写一下,在以后研究中,还会继续补充程序原理. 一:容错 1.机制 在集群调用失败时,Dubbo 提供了多种容错方案,缺省为 failove ...
- Ionic Js一:上拉菜单(ActionSheet)
上拉菜单(ActionSheet)通过往上弹出的框,来让用户选择选项. 非常危险的选项会以高亮的红色来让人第一时间识别.你可以通过点击取消按钮或者点击空白的地方来让它消失. HTML 代码 <b ...
- 决策树 (decision tree)
内容学习于 ApacheCN github 定义: 分类决策树模型是一种描述对实例进行分类的树形结构.决策树由结点(node)和有向边(directed edge)组成.结点有两种类型:内部结点(in ...
- Pytho并发编程-利用协程实现简单爬虫
from gevent import monkey;monkey.patch_all() import gevent from urllib.request import urlopen def ge ...
- [js]正则篇
一.正则基本概念 1.一种规则.模式.文本处理工具 2.强大的字符串匹配工具 3.在js中常与字符串函数配合使用 二.js正则写法 正则在js中以正则对象存在: (1)var re=new RegEx ...
- jdk1.8下字符串常量的判断,String.intern()分析
字符串常量池在jdk升级过程中发生了一些变化 在JDK1.6中,它在方法区中,属于“永久代”. 在JDK1.7中,它被移除方法区,放在java堆中. 在JDK1.8中,取消了“永久代”,将常量池放在元 ...
- 转 Java高级程序员面试题
1.你认为项目中最重要的过程是那些? 分析.设计阶段 尽量找出进度的优先级 2.如果给你一个4-6人的team,怎么分配? 挑选一技术过硬的人作为我的替补.其它人平均分配任务,每周进行全面的任务分配 ...
- MySQL数据库sql语句
零.用户管理: 1.新建用户: >CREATE USER name IDENTIFIED BY 'ssapdrow'; 2.更改密码: >SET PASSWORD FOR name=PAS ...
- 【BZOJ 2986】 莫比乌斯函数+容斥原理
2986: Non-Squarefree Numbers Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 337 Solved: 156 Descri ...