[BZOJ 3653] 谈笑风生
题目
给定一棵 n 个点的有根树,另有 q 次询问,每次询问给定
a、k,求有多少个点对 (b, c) 满足 a、b、c 两两不同,a、b 都是
c 的祖先且 a、b 间距离不超过 k。 n, q ≤ 3 × 10^5。
思路
有两种情况。当 b 是 a 的祖先时,b 在 a 的 1 至 k 级祖先
中任选,c 在 a 的子树内任选。
当 b 在 a 子树内时,要求 depb ≤ depa + k,c 在 b 的子树
内任选。可以用主席树(或线段树合并)维护 a 子树内、dep 在
某个区间限制内的 size 和。
代码
#include <cstdio>
#include <algorithm>
#define MAXN 300003
#define MAXM 300003*30
#define ll long long
using namespace std;
int head[MAXN],nxt[MAXN*2],vv[MAXN*2],tot;
inline void add_edge(int u, int v){vv[++tot]=v;nxt[tot]=head[u];head[u]=tot;
}
int cnt;
ll tre[MAXM*2];
int sl[MAXM*2],sr[MAXM*2];
void change(int &x, int l, int r, int pos, int val){if(x==0) x=++cnt;tre[x]+=val;if(l==r) return;int mid=(l+r)>>1;if(pos<=mid) change(sl[x], l, mid, pos, val);else change(sr[x], mid+1, r, pos, val);
}
ll query(int x, int l, int r, int ql, int qr){if(x==0) return 0;if(ql<=l&&r<=qr) return tre[x];int mid=(l+r)>>1;ll res=0;if(ql<=mid) res+=query(sl[x], l, mid, ql, qr);if(mid<qr) res+=query(sr[x], mid+1, r, ql, qr);return res;
}
int merge(int a, int b, int l, int r){if(a==0||b==0) return a+b;int mid=(l+r)>>1;int x=++cnt;tre[x]=tre[a]+tre[b];sl[x]=merge(sl[a], sl[b], l, mid);sr[x]=merge(sr[a], sr[b], mid+1, r);return x;
}
int n,q;
int sz[MAXN],rot[MAXN],dep[MAXN];
void dfs(int u, int fa){sz[u]=1;dep[u]=dep[fa]+1;for(int i=head[u];i;i=nxt[i]){int v=vv[i];if(v==fa) continue;dfs(v, u);sz[u]+=sz[v];}change(rot[u], 1, n, dep[u], sz[u]-1);rot[fa]=merge(rot[fa], rot[u], 1, n);
}
int main(){scanf("%d %d", &n, &q);for(int i=1;i<n;++i){int a,b;scanf("%d %d", &a, &b);add_edge(a, b);add_edge(b, a);}dfs(1, 0);while(q--){int p,k;scanf("%d %d", &p, &k);printf("%lld\n", query(rot[p], 1, n, dep[p]+1, dep[p]+k)+(ll)(sz[p]-1)*min(k, dep[p]-1));}return 0;
}
[BZOJ 3653] 谈笑风生相关推荐
- [BZOJ 3653]谈笑风生
[BZOJ 3653] 谈笑风生 题意 给定一棵 \(n\) 个点根为 \(1\) 单位权值的树以及 \(q\) 个查询, 每次查询给定 \(p\) 和 \(k\), 求满足 \(a,p\) 都是 \ ...
- BZOJ 3653: 谈笑风生(离线, 长链剖分, 后缀和)
题意 给你一颗有 \(n\) 个点并且以 \(1\) 为根的树.共有 \(q\) 次询问,每次询问两个参数 \(p, k\) .询问有多少对点 \((p, a, b)\) 满足 \(p,a,b\) 为 ...
- 【刷题】BZOJ 3653 谈笑风生
Description 设T 为一棵有根树,我们做如下的定义: ? 设a和b为T 中的两个不同节点.如果a是b的祖先,那么称"a比b不知道 高明到哪里去了". ? 设a 和 b 为 ...
- BZOJ 3653 谈笑风生
Problem BZOJ 然而是权限题,如果你像蒟蒻我一样没有权限号请上洛谷~ Solution 据说正解是主席树??? 不管了,反正主席树常数巨大,线段树虽然暴力好歹也能卡过去,而且这题数据还比较水 ...
- BZOJ 3653: 谈笑风生
题目在这里呀! 个人认为是一道很好的题目,原来可持久化线段树还能这么用,看题解之前还是没有想到啦要批评!那就写个题解补偿一下? 题意 给你一棵有根树,n个节点,有q次询问,每次询问,给出两个数x(1& ...
- BZOJ #3653. 谈笑风生
题目 题意: 给定一棵树. 询问给定b,kb,kb,k,现在要选择两个距离b≤kb\le kb≤k单位的点a,ca,ca,c,使得a,ba,ba,b都是ccc的祖先. 问总选择方案数. n,q≤3e5 ...
- 3653: 谈笑风生
3653: 谈笑风生 链接 分析: $ans = min(deep[x] - 1, k) * siz[x] - 1 +\sum\limits_{y是u子树内的点}(siz[y] - 1)$ 前面的可以 ...
- bzoj 3653 [湖南集训]谈笑风生
题目描述 设 T 为一棵有根树,我们做如下的定义: • 设 a 和 b 为 T 中的两个不同节点.如果 a 是 b 的祖先,那么称"a 比 b 不知道高明到哪里去了". • 设 a ...
- 【BZOJ 3653】谈笑风生
传送门 Problem 给出一个有 nnn 个点的有根树,根节点为 111,边的长度为 111. 有 qqq 个询问,询问给定两个整数 ppp 和 kkk,问有多少个有序三元组 (a,b,c)(a,b ...
最新文章
- 技术总监,被判刑12年!因公司未兑现股权,愤怒植入代码,牟利333万
- 打印数组算法:堆栈与深度优先搜索(迷宫问题)
- hdu 1573(中国剩余定理非互质情况)
- WebSen!NT的行业分类说明
- laravel increment出现了翻倍递增_股票连续多少个涨停板就可以市值翻倍?
- 首次击败美国!2019《财富》世界500强公布:129家中国公司上榜
- batch size自适应log(1)
- HTML、CSS、JS对unicode字符的不同处理
- pandas 作图 统计_pandas数据作图方法
- 关于java中的httpsession_JavaWeb——HttpSession
- chmod 755 与chmod +x的区别
- php爬虫亚马逊,亚马逊爬虫(亚马逊 api)
- Java基础 第一节 第一课
- 大数据分析图形绘制如何进行?
- 记:解决 Weditor 页面元素坐标定位不到、不准确的问题
- 基于OpenCV DNN模块给黑白老照片上色(附Python/C++源码)
- Python3中StringIO
- Python项目对接CAS方案
- 嫁给玩股票男人的九大理由
- 【JUnit学习笔记】1:使用JUnit4进行简易单元测试的例子
热门文章
- java手机号中间4位使用*替换
- xp外观主题下载_增强Windows XP外观的简便方法
- 100个精选Python实战项目案例,初学者练手必备
- 本科三本的计算机博士,读书中的我 从三本本科到985博士
- 怎么查看笔记本内存条型号_怎么查看笔记本内存条型号?2种查看笔记本内存型号方法...
- android emoji转换成字符串,安卓的emoji表情转换为文字
- 骗子网站--正规网赚系统--www.j9m2.com--诈骗网站
- 计算机硬盘灯不亮,解决办法:如果计算机硬盘驱动器指示灯不亮,该怎么办?解决电脑硬盘指示灯不亮的问题_IT / computer_资料...
- 迅雷再换赛道锁定云计算 盈利能力待考
- Uber vs. Lyft