题目

你有一棵 \(n\) 节点的树 ,回答 \(m\) 个询问,每次询问给你两个整数 \(l,r\) ,问存在多少个整数 \(k\) 使得从 \(l\) 沿着 \(l \to r\) 的简单路径走 \(k\) 步恰好到达 \(k\) 。

分析

考虑离线后按链记贡献

从 \(l\) 到 \(lca(l,r)\) 这段链上,可以计入贡献的点 \(x\) 满足 \(dep[l]-x=dep[x]\),称为一类贡献

即 \(dep[x]+x=dep[l]\), 因为已知 \(dep[l]\),所以直接开桶计算

从 \(lca(l,r)\) 到 \(r\) 这段链上,可以计入贡献的点 \(x\) 满足 \(dep[lca]+(x-dep[l]-dep[lca])=dep[x]\),称为二类贡献

即 \(dep[x]-x=2\times dep[lca]-dep[l]\),同样可以直接开另一个桶计算

因为 \(dfs\) 下来时桶记录的是根到当前点的信息,所以算贡献的时候要减去 \(lca\) 处的假贡献

\(lca\) 也可能成为需要贡献,所以算二类贡献的时候减去 \(father_{lca}\) 处的贡献

具体细节体现在代码

\(Code\)

#include<cstdio>
#include<vector>
using namespace std; const int N = 3e5 + 5;
int n, m, dep[N], d[2][2*N], fa[N], da[N], vis[N], l[N], r[N], lca[N], ans[N];
vector<int> e[N];
struct node1{int x, id;};
vector<node1> q1[N];
struct node2{int cs, ty, f, id;};
vector<node2> q2[N]; int find(int x){return fa[x] == x ? x : fa[x] = find(fa[x]);}
void dfs(int x, int dad)
{
da[x] = dad, dep[x] = dep[dad] + 1;
for(register int i = 0; i < e[x].size(); i++)
{
if (e[x][i] == dad) continue;
dfs(e[x][i], x);
}
}
void dfs1(int x, int dad)
{
vis[x] = 1;
for(register int i = 0; i < e[x].size(); i++)
{
if (e[x][i] == dad) continue;
dfs1(e[x][i], x), fa[e[x][i]] = x;
}
for(register int i = 0; i < q1[x].size(); i++)
if (vis[q1[x][i].x]) lca[q1[x][i].id] = find(q1[x][i].x);
}
void dfs2(int x, int dad)
{
++d[0][dep[x] + x], ++d[1][dep[x] - x + n];
for(register int i = 0; i < q2[x].size(); i++)
ans[q2[x][i].id] += q2[x][i].f * d[q2[x][i].ty][q2[x][i].cs];
for(register int i = 0; i < e[x].size(); i++)
{
if (e[x][i] == dad) continue;
dfs2(e[x][i], x);
}
--d[0][dep[x] + x], --d[1][dep[x] - x + n];
} int main()
{
freopen("query.in" , "r" , stdin);
freopen("query.out" , "w" , stdout);
scanf("%d%d" , &n , &m);
int x , y;
for(register int i = 1; i < n; i++)
{
scanf("%d%d" , &x , &y);
e[x].push_back(y), e[y].push_back(x);
}
for(register int i = 1; i <= m; i++)
{
scanf("%d%d" , &l[i], &r[i]);
q1[l[i]].push_back(node1{r[i], i});
q1[r[i]].push_back(node1{l[i], i});
}
for(register int i = 1; i <= n; i++) fa[i] = i;
dfs(1, 0), dfs1(1, 0);
for(register int i = 1; i <= m; i++)
{
q2[l[i]].push_back(node2{dep[l[i]], 0, 1, i});
q2[lca[i]].push_back(node2{dep[l[i]], 0, -1, i});
q2[r[i]].push_back(node2{2*dep[lca[i]]-dep[l[i]]+n, 1, 1, i});
if (lca[i] > 1)
q2[da[lca[i]]].push_back(node2{2*dep[lca[i]]-dep[l[i]]+n, 1, -1, i});
}
dfs2(1, 0);
for(register int i = 1; i <= m; i++) printf("%d\n" , ans[i]);
}

JZOJ 6904. 【2020.11.28提高组模拟】T3 树上询问(query)的更多相关文章

  1. 【2020.11.28提高组模拟】T1染色(color)

    [2020.11.28提高组模拟]T1染色(color) 题目 题目描述 给定 \(n\),你现在需要给整数 \(1\) 到 \(n\) 进行染色,使得对于所有的 \(1\leq i<j\leq ...

  2. 【2020.11.28提高组模拟】T2 序列(array)

    序列(array) 题目描述 ​给定一个长为 \(m\) 的序列 \(a\). 有一个长为 \(m\) 的序列 \(b\),需满足 \(0\leq b_i \leq n\),\(\sum_{i=1}^ ...

  3. 【2020.11.30提高组模拟】剪辣椒(chilli)

    剪辣椒(chilli) 题目描述 在花园里劳累了一上午之后,你决定用自己种的干辣椒奖励自己. 你有n个辣椒,这些辣椒用n-1条绳子连接在一起,任意两个辣椒通过用若干个绳子相连,即形成一棵树. 你决定分 ...

  4. 【2020.11.30提高组模拟】删边(delete)

    删边(delete) 题目 题目描述 给你一棵n个结点的树,每个结点有一个权值,删除一条边的费用为该边连接的两个子树中结点权值最大值之和.现要删除树中的所有边,删除边的顺序可以任意设定,请计算出所有方 ...

  5. 11.5NOIP2018提高组模拟题

    书信(letter) Description 有 n 个小朋友, 编号为 1 到 n, 他们每人写了一封信, 放到了一个信箱里, 接下来每个人从中抽取一封书信. 显然, 这样一共有 n!种拿到书信的情 ...

  6. 【2020.12.03提高组模拟】A组反思

    估计:40+10+0+0=50 实际:40+10+0+0=50 rank40 T1 赛时看到\(n,m\leq9\),我当机立断决定打表,暴力打了几个点之后发现在\(n\ne m\)且\(k\ne0\ ...

  7. 【2020.12.01提高组模拟】卡特兰数(catalan)

    题目 题目描述 今天,接触信息学不久的小\(A\)刚刚学习了卡特兰数. 卡特兰数的一个经典定义是,将\(n\)个数依次入栈,合法的出栈序列个数. 小\(A\)觉得这样的情况太平凡了.于是,他给出了\( ...

  8. 【2020.12.01提高组模拟】A组反思

    105,rk45 T1 赛时一开始先打了\(m=0\)的情况,也就是普通的卡特兰数,然后打了暴力,样例过了,把样例改改就不行了,原因没有保证是枚举的是合法的出栈序列 得分:\(WA\&TLE1 ...

  9. 求hack or 证明(【JZOJ 4923】 【NOIP2017提高组模拟12.17】巧克力狂欢)

    前言 本人在此题有一种不是题解的方法,但无法证明也找不到反例. 如果各位大神有反例或证明请发至 邮箱:qq1350742779@163.com Description Alice和Bob有一棵树(无根 ...

  10. 【2020.12.02提高组模拟】A组反思

    55,rk47 T1 赛时先想了\(trie\),想到不一定是前缀,然后就放弃转为打暴力 得分:\(RE22\) 正解是只用判断\(i\)与\(i+1\)的关系,那么只有两种情况,判断一下然后\(dp ...

随机推荐

  1. Python3.7.3安装TensorFlow和OpenCV3

    根据python的版本进行下载相应的文件 一.安装TensorFlow 进入网址https://pypi.org/project/tensorflow/#files下载TensorFlow文件 进入下 ...

  2. 输出图形字符的命令 banner

    输出图形字符的命令 banner 有趣的 Linux 命令.来自实验楼操作系统课程 安装 sudo apt install sysvbanner 截图 其他 还有两个类似的命令toilet,figle ...

  3. 跟我学Python图像处理丨图像分类原理与案例

    摘要:本篇文章将分享图像分类原理,并介绍基于KNN.朴素贝叶斯算法的图像分类案例. 本文分享自华为云社区<[Python图像处理] 二十六.图像分类原理及基于KNN.朴素贝叶斯算法的图像分类案例 ...

  4. 记一次InputStream流读取不完整留下的惨痛教训

    前言 首先,问问大家下面这段流读取的代码是否存在问题呢? inputStream = .... try { // 根据inputStream的长度创建字节数组 byte[] arrayOfByte = ...

  5. DC-9靶场练习

    Vulnhub靶场-DC-9 准备工作 kali和靶机都选择NAT模式(kali与靶机同网段) 下载链接:https://download.vulnhub.com/dc/DC-9.zip 一.主机发现 ...

  6. elasticsearch倒排索引(全面了解)

    SimpleAI推荐语: 前年转过这篇文章,最近在看检索相关论文,发现又有点忘记倒排索引(inverted index)的具体内容,遂翻出来再看看,不得不说,这个漫画画的太好了,娓娓道来,一看就懂,再 ...

  7. 笑死,面试官又问我SpringBoot自动配置原理

    面试官:好久没见,甚是想念.今天来聊聊SpringBoot的自动配置吧? 候选者:嗯,SpringBoot的自动配置我觉得是SpringBoot很重要的"特性"了.众所周知,Spr ...

  8. [机器学习] Yellowbrick使用笔记4-目标可视化

    目标可视化工具专门用于直观地描述用于监督建模的因变量,通常称为y目标. 代码下载 当前实现了以下可视化: 平衡箱可视化Balanced Binning:生成带有垂直线的直方图,垂直线显示推荐值点,以将 ...

  9. SSM框架——MyBatis

    Mybatis 1.Mybatis的使用 1.1给项目导入相关依赖 我这里有几个下载好的依赖包提供给大家 点我下载--junit4.13.2 点我下载--maven3.8.1 点我下载--mybati ...

  10. Miller_Rabin质数测试

    数论 Miller_Rabin质数测试 作用 当需要判断一个数字是否是质数时,又发现数字过大,\(0(\sqrt n)\)难以承受的时候,就可以使用Miller_Rabin质数测试 基本定理 定理一, ...