JZOJ 6904. 【2020.11.28提高组模拟】T3 树上询问(query)
题目
你有一棵 \(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)的更多相关文章
- 【2020.11.28提高组模拟】T1染色(color)
[2020.11.28提高组模拟]T1染色(color) 题目 题目描述 给定 \(n\),你现在需要给整数 \(1\) 到 \(n\) 进行染色,使得对于所有的 \(1\leq i<j\leq ...
- 【2020.11.28提高组模拟】T2 序列(array)
序列(array) 题目描述 给定一个长为 \(m\) 的序列 \(a\). 有一个长为 \(m\) 的序列 \(b\),需满足 \(0\leq b_i \leq n\),\(\sum_{i=1}^ ...
- 【2020.11.30提高组模拟】剪辣椒(chilli)
剪辣椒(chilli) 题目描述 在花园里劳累了一上午之后,你决定用自己种的干辣椒奖励自己. 你有n个辣椒,这些辣椒用n-1条绳子连接在一起,任意两个辣椒通过用若干个绳子相连,即形成一棵树. 你决定分 ...
- 【2020.11.30提高组模拟】删边(delete)
删边(delete) 题目 题目描述 给你一棵n个结点的树,每个结点有一个权值,删除一条边的费用为该边连接的两个子树中结点权值最大值之和.现要删除树中的所有边,删除边的顺序可以任意设定,请计算出所有方 ...
- 11.5NOIP2018提高组模拟题
书信(letter) Description 有 n 个小朋友, 编号为 1 到 n, 他们每人写了一封信, 放到了一个信箱里, 接下来每个人从中抽取一封书信. 显然, 这样一共有 n!种拿到书信的情 ...
- 【2020.12.03提高组模拟】A组反思
估计:40+10+0+0=50 实际:40+10+0+0=50 rank40 T1 赛时看到\(n,m\leq9\),我当机立断决定打表,暴力打了几个点之后发现在\(n\ne m\)且\(k\ne0\ ...
- 【2020.12.01提高组模拟】卡特兰数(catalan)
题目 题目描述 今天,接触信息学不久的小\(A\)刚刚学习了卡特兰数. 卡特兰数的一个经典定义是,将\(n\)个数依次入栈,合法的出栈序列个数. 小\(A\)觉得这样的情况太平凡了.于是,他给出了\( ...
- 【2020.12.01提高组模拟】A组反思
105,rk45 T1 赛时一开始先打了\(m=0\)的情况,也就是普通的卡特兰数,然后打了暴力,样例过了,把样例改改就不行了,原因没有保证是枚举的是合法的出栈序列 得分:\(WA\&TLE1 ...
- 求hack or 证明(【JZOJ 4923】 【NOIP2017提高组模拟12.17】巧克力狂欢)
前言 本人在此题有一种不是题解的方法,但无法证明也找不到反例. 如果各位大神有反例或证明请发至 邮箱:qq1350742779@163.com Description Alice和Bob有一棵树(无根 ...
- 【2020.12.02提高组模拟】A组反思
55,rk47 T1 赛时先想了\(trie\),想到不一定是前缀,然后就放弃转为打暴力 得分:\(RE22\) 正解是只用判断\(i\)与\(i+1\)的关系,那么只有两种情况,判断一下然后\(dp ...
随机推荐
- Cookie添加方法
Cookie是通过response对象中的getCookie()方法进行获得的
- this关键字在JAVA和JS中的异同
this在JS中的用法 由于js中this 是在运行期进行绑定的,所以js中的 this 可以是全局对象.当前对象或者任意对象,这完全取决于函数的调用方式.JavaScript 中函数的调用有以下几种 ...
- C++基础语法学习:STL
基础语法学习,少点比较,多些谦虚 1.容器: 常见的容器有以下几类: 1.vector:向量 2.deque:双端队列 3.list:列表 4.set:集合 5:multiset:多重集合 6.map ...
- Chaos 测试下的若干 NebulaGraph Raft 问题分析
Raft 是一种广泛使用的分布式共识算法.NebulaGraph 底层采用 Raft 算法实现 metad 和 storaged 的分布式功能.Raft 算法使 NebulaGraph 中的 meta ...
- Navicat破解教程
一.注意: 软件适用于WIN7/8/10/11: 安装全程断网: 下载.解压和安装都应该在英文路径下进行: 解压安装前关闭所有杀毒软件,WIN10/11系统需关闭Windows Defender的实时 ...
- P1314 聪明的质监员(题解)
题目 小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 \(n\) 个矿石,从 \(1\) 到 \(n\) 逐一编号,每个矿石都有自己的重量 \(w_i\) 以及价值 \(v_i\) ...
- 基于Unet+opencv实现天空对象的分割、替换和美化
传统图像处理算法进行"天空分割"存在精度问题且调参复杂,无法很好地应对云雾.阴霾等情况:本篇文章分享的"基于Unet+opencv实现天空对象的分割.替换和 ...
- 2、Java封装、继承与多态
/** * 类.对象.面向过程.面向对象的理解: * 1.类:类是封装对象的属性和方法的载体 * * 2.对象:对象是类抽象出来的一个实例 * * 3.面向过程:面向过程注重的是具体的实现过程,因果关 ...
- Spark详解(05) - Spark核心编程SparkCore
Spark详解(05) - Spark核心编程SparkCore RDD概述 什么是RDD RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基 ...
- Kubernetes 部署 - DevOps CI/CD详细指南
什么是Kubernetes部署? 在此文章中,我们将探索Kubernetes(K8s),结合DigitalOcean Kubernetes集群与Buddy自动化运维系统部署以达到以下列出的目标: 使 ...