【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之 ...
随机推荐
- Django项目从零开始的大概脉络
Django项目从零开始脉络 创建虚拟环境,隔离项目python环境:mkvirtualenv -p /usr/bin/python3.6 envname 安装Django:pip install d ...
- 选择 React Native 的理由
转载:选择 React Native 的理由 从开始知道 React Native 到现在已经过了5个月,真实的试用也经历了三个月的时间.阅读文档开始,了解是什么,到简单的理解为什么,都是在聆听不同的 ...
- 【SQL】185. Department Top Three Salaries
The Employee table holds all employees. Every employee has an Id, and there is also a column for the ...
- web服务端安全之权限漏洞
一.权限漏洞 访问控制是指用户对系统所有访问的权限控制,通常包含水平权限,和垂直权限. 水平越权:同一角色级别的用户之间所产生的问题,如A用户可以未授权访问B用户的数据: 垂直越权:不同角色级别的用户 ...
- 你的跑步姿势正确吗? 教你正确跑步姿势 & 常识
转载!!!!!搞IT必须运动一下 前言: 最近两年跑步的人越来越多,跑步在大部分人的观念中都是毫无技术含量,只要迈开腿就行了,其实这也是造成大多数跑步人士伤病的根源.对跑步的认知不足,跑步是一项看起来 ...
- opencv 掩膜操作 滤波 卷积核定义 增强对比度 掩膜运算
/* 矩阵的掩膜操作 0 掩膜mask 在这里进行增强对比度: [ [ 0,-1, 0 ], [-1, 5, -1], [ 0,-1, 0 ] ] 使用mask滑动图片每一个位置,进行卷积运算 这里这 ...
- 希尔排序之C++实现(初级版)
希尔排序之C++实现(初级版) 一.源代码:希尔排序之C++实现(初级版) /*希尔排序基本思想: 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组. 所有距离为d1的倍数的记录放在同一个 ...
- Spring之Spring环境搭建
Spring之Spring环境搭建 一.什么是Spring? Spring框架是由于软件开发的复杂性而创建的.Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情.然而,Spr ...
- luoguP4466 [国际集训队]和与积 莫比乌斯反演
自然想到枚举\(gcd(a, b)\),不妨设其为\(d\),并且\(a = di, b = dj(a > b)\) 那么\(\frac{ab}{a + b} = \frac{dij}{i + ...
- 【漏洞预警】Intel爆CPU设计问题,导致win和Linux内核重设计(附测试poc)
目前研究人员正抓紧检查 Linux 内核的安全问题,与此同时,微软也预计将在本月补丁日公开介绍 Windows 操作系统的相关变更. 而 Linux 和 Windows 系统的这些更新势必会对 Int ...