题目:

松鼠的新家是一棵树,前几天刚刚装修好了新家,新家有 个房间,并且有 根树枝连接,每个房间都可以相互到达,且任两个房间之间的路线都是唯一的。天哪,他居然真的住在「树」上。松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去 ,再去 ,……,最后到 ,来参观新家。

可是这样会导致维尼重复走很多房间,懒惰的维尼不停地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。维尼是个馋家伙,立马就答应了。

现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间 是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。

样例输入:

5
1 4 5 3 2
1 2
2 4
2 3
4 5

样例输出:

1
2
1
2
1

题解:

大思路:

读完题我们不难发现:假设路径为a[1]–>a[2]–>a[3]–>…–>a[n],若要从a[i]到a[j]那么在它走过的路径上我们要放一颗糖,因为要最少所以不难想到走最短的路,那么就是走a[i]->lca(a[i], a[j])->a[j],然后再将这段路每一个点加上1。

细节:

那么如何将a[i]->lca(a[i], a[j])->a[j]这段路每一个点加上1呢,这需要用到我们的“树上点差分”:如图若要求U->lca(U, V)->V这段路所有点加1,则首先我们要将U,V点加1,然后再将lca和lca的父节点减1,最后如果要求某一结点的值那么则将它的子树(包括他自己)加起来求和,最后和即为答案。
为什么是这样呢?

如图若我们将某一结点加1,再对它的父节点求子树和,那么所有的父节点都会有影响,但是我们的目的是让U->lca(U, V)->V这段路所有点加1,所以就要将多余的剪掉:首先lca这个点要减1,因为求子数和的话它会是2,但实际上他是1,然后就是lca的父节点,不难看到它和我们这条路段没有关系,但是却加了个1,所以同样将他减1,这样操作后就只有这段路被加了1,其他节点并未影响。
(感觉与写普通差分方法很类似)
这样算出来我们会发现1以后的节点被多算了1,这是因为在求差分数组时我们将后面的节点既作为起点又作为终点算了两遍,所以要剔除。

for(int i = 2;i <= n; i++) ans[a[i]]--;

代码:

#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
#include <cstring>
using namespace std;
const int MAXN = 300005;
int n, v[MAXN * 2], head[MAXN], _next[MAXN * 2], tot, d[MAXN], fa[MAXN][55], lu, q, chafen[MAXN];
queue<int> qu;
int ans[MAXN], a[MAXN];
void add(int x, int y) {v[++tot] = y;_next[tot] = head[x];head[x] = tot;
}void bfs() {d[1] = 1;qu.push(1);while (!qu.empty()) {int qi = qu.front();qu.pop();for (int i = head[qi]; i; i = _next[i]) {int son = v[i];if (d[son])continue;d[son] = d[qi] + 1;fa[son][0] = qi;for (int j = 1; j <= lu; j++) fa[son][j] = fa[fa[son][j - 1]][j - 1];qu.push(son);}}
}int LCA(int a, int b) {fa[1][0] = 1;if (d[a] > d[b])swap(a, b);for (int i = lu; i >= 0; i--) {if (d[fa[b][i]] >= d[a]) {b = fa[b][i];}}if (a == b)return a;for (int i = lu; i >= 0; i--) {if (fa[b][i] != fa[a][i]) {a = fa[a][i];b = fa[b][i];}}return fa[a][0];
}void dfs(int x, int father) {//dfs求子树和for(int i = head[x];i;i = _next[i]) {int y = v[i];if(y != father) {dfs(y, x);chafen[x] += chafen[y];}}
}
int main() {scanf("%d", &n);int x, y;for(int i = 1;i <= n; i++) scanf("%d", &a[i]);for (int i = 1; i <= n - 1; i++) {scanf("%d %d", &x, &y);add(x, y);add(y, x);}lu = (int)(log(n) / log(2)) + 1;bfs();for(int i = 2;i <= n; i++) {int lca = LCA(a[i], a[i - 1]);chafen[lca]--;chafen[a[i]]++;chafen[a[i - 1]]++;if(lca != 1) chafen[fa[lca][0]]--;}dfs(1, -1);for(int i = 1; i <= n; i++) {if(i != a[1]) printf("%d\n", chafen[i] - 1);else printf("%d\n", chafen[i]);}return 0;
}

松鼠的新家(树上点差分 + LCA)相关推荐

  1. 洛谷 P3258 [JLOI2014]松鼠的新家 树上差分

    缘起 [1]中我们学习了树上差分,并且a了一个裸的点差分. 现在继续树上差分~ 洛谷 P3258 [JLOI2014]松鼠的新家 分析 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房 ...

  2. P3258[JLOI2014]松鼠的新家(LCA 树上差分)

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  3. bzoj 3631: [JLOI2014]松鼠的新家(LCA+树上差分)

    3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 2059  Solved: 1030 [Submit][S ...

  4. P3258 [JLOI2014]松鼠的新家(树上点查分)

    题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在"树"上. ...

  5. [Luogu 3258] JLOI2014 松鼠的新家

    [Luogu 3258] JLOI2014 松鼠的新家 LCA + 树上差分. 我呢,因为是树剖求的 LCA,预处理了 DFN(DFS 序),于是简化成了序列差分. qwq不讲了不讲了,贴代码. #i ...

  6. P3258 [JLOI2014]松鼠的新家

    文章目录 题意: 题解: 树上差分 代码: 树链剖分 代码: P3258 [JLOI2014]松鼠的新家 题意: n个点,n-1条边,给出每个点的拜访顺序,问每个点经过几次(最后一次移动不算拜访) 题 ...

  7. Luogu_P3258 松鼠的新家

    松鼠的新家 链接 Luogu_P3258 松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有nnn个房间,并且有n−1n-1n−1根树枝连接,每个房间都可以相互到达,且俩个房间之间 ...

  8. 刷题总结——松鼠的新家(bzoj3631)

    题目: Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在" ...

  9. BZOJ3631 [JLOI2014]松鼠的新家

    Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在"树&q ...

最新文章

  1. ply补全为立方体_ply 点云文件格式
  2. php调用以太坊geth API说明
  3. js时断时续————动态参数传递
  4. NSOperation的使用细节 [1]
  5. Asp.Net ajax 面向对象类型系统2 - 使用事件
  6. linux 日志报告生成器,Linux报告生成器工具awk
  7. iOS 自定义底部tabbar加号按钮实现方法
  8. easyui添加删除表格任意行
  9. 水系图一般在哪里找得到_真空排水系统在综合管廊工程中的应用探讨
  10. cpu与计算机其他的通信,PC与CPU224 通讯
  11. erdas几何校正_ERDAS遥感图像的几何校正.docx
  12. mac开机启动项怎么设置,苹果电脑开机启动项在哪里设置
  13. Unity开发Android游戏(三)虚拟摇杆之_Easy Touch 5
  14. 如果本地连接受限或无连接的解决方法
  15. B站又被搞了,这次全部下载它
  16. 客服对于Kindle电子书的退货、倒闭、VR等问题的回答
  17. shell for 循环
  18. 【论文笔记】ASYMMETRIC SELF-PLAY FOR AUTOMATIC GOAL DISCOVERY IN ROBOTIC MANIPULATION
  19. 关于opencv的实战——银行卡号识别
  20. 【OpenCV】图像梯度处理

热门文章

  1. iOS xcode9中framework静态库的创建以及xib和图片的使用记录
  2. 史上最全软件测试入门到精通【测试+测开】
  3. 圆和圆柱体计算(继承)Python
  4. 高中数学必修3知识点总结归纳:第一章算法初步
  5. 如何查询澳大利亚药监局(TGA)药品信息数据
  6. 游戏设计的艺术:一本透镜的书——第二十五章 好的游戏是通过游戏测试做出来的
  7. NANO开发套件SD卡烧录+opencv配置+tensorrt+cuda10.2
  8. Python Basic - GIL:global interpreter lock(全局解释器锁)
  9. 金融业信贷风控算法4-python的入门和介绍
  10. 弹性事务框架ETF4J——面向Java微服务的交易最终一致性解决方案