题目

你有一棵 \(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. psutil.AccessDenied: psutil.AccessDenied

    解决办法 import psutil for proc in psutil.process_iter(): try: print(proc.name()) except (psutil.NoSuchP ...

  2. 获取联通光猫PT952G的管理员密码

    前言 普通用户的帐号和密码在光猫的背面 输入光猫网关即可跳转到登录界面 但是没有什么权限操作东西,所以我找到了管理员界面 输入 网关+cu.html 即可跳转到管理员界面 例如我这里是http://1 ...

  3. 记一次windows10电脑连上wifi无法上网的解决问题

    前言 今天下午同学的电脑能连上wifi,但是却上不了互联网 开始思考 首先想到的肯定是WiFi驱动问题,但是wifi能连上大部分的原因可能就不是驱动问题了,为了彻底排除这个因素,我用到了我的usb网卡 ...

  4. 实践案例:平安健康的 Dubbo3 迁移历程总结

    本篇是 Apache Dubbo 的实践案例.感兴趣的朋友可以访问官网了解更多详情,或搜索关注官方微信公众号 Apache Dubbo 跟进最新动态. 1 背景 我们公司从15年开始就使⽤dubbo作 ...

  5. selenium常用配置

    def init_chrome_options(self,): chrome_options = webdriver.ChromeOptions() # 设置浏览器初始 位置x,y & 宽高x ...

  6. vue项目封装 axios 和 api

    一,utils文件夹下新建一个request.js文件 import axios from 'axios'; import QS from 'qs'; import { Toast } from 'v ...

  7. JavaScript:立即执行函数

    想象一下,如果我希望某个代码块,只执行一次,就不再执行,应该怎么办? 代码块肯定是用函数来表示,执行肯定是调用函数,但是确保只执行一次,该怎么办? 我们为什么可以多次调用函数,因为函数名指向了函数的内 ...

  8. [OpenCV实战]49 对极几何与立体视觉初探

    本文主要介绍对极几何(Epipolar Geometry)与立体视觉(Stereo Vision)的相关知识.对极几何简单点来说,其目的就是描述是两幅视图之间的内部对应关系,用来对立体视觉进行建模,实 ...

  9. MySQL优化三,SQL语法

    ## 1.3.MySQL调优 前言:在前面的基础之上把相应的数据库表设计得很完美,建立了好用的索引,如果SQL语句中没有使用到相应索引的话,也是白搭,如何设计好一点的SQL,则是一大问题 ### 1. ...

  10. C组合方案

    递归实现组合型枚举 从 1∼n 这 n 个整数中随机选出 m 个,输出所有可能的选择方案. 输入格式 两个整数 n,m ,在同一行用空格隔开. 输出格式 按照从小到大的顺序输出所有方案,每行 1 个. ...