P3258 [JLOI2014]松鼠的新家

题目描述

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

松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,......,最后到an,去参观新家。可是这样会导致维尼重复走很多房间,懒惰的维尼不停地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。

维尼是个馋家伙,立马就答应了。现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。

因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。

输入格式

第一行一个整数n,表示房间个数第二行n个整数,依次描述a1-an

接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。

输出格式

一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让维尼有糖果吃。

输入输出样例

输入 #1

5

1 4 5 3 2

1 2

2 4

2 3

4 5

输出 #1

1

2

1

2

1

说明/提示

2<= n <=300000

【思路】

倍增/树链剖分 + 树上差分

很有意思很有意思的一道题目

会了树上差分几乎就是一个板子题

不,是两个板子题

倍增/树链剖分板子 + 树上差分板子

先dfs出这棵树每个点的深度和他跳2^n之后会跳到哪一个点

然后按照题目给出的到达房间的顺序

找 \(a_1\)和 \(a_2\)的LCA, \(a_2\) 和 \(a_3\) 的LCA……

然后运用树上差分

将 \(a_i\) 和 \(a_i+1\) 的差分数组都加上1,

然后将LCA和LCA夫妻的差分数组都减去1

最后一个递归递归出每个店的值

输出就好了

注意:

这里有n-1个点作为了起点也作为了终点

所以重复了1次

判断一下重复过的在输出的时候顺手减去1就好了

【完整代码】

#include<iostream>
#include<cstdio>
#include<algorithm> using namespace std;
const int Max = 300005;
struct node
{
int y;
int ne;
}s[Max << 1];
int a[Max];
int depth[Max];
int fa[Max][23];
int head[Max];
int sum = 0;
int c[Max];
int ans[Max]; void add(int x,int y)
{
s[++ sum].y = y;
s[sum].ne = head[x];
head[x] = sum; s[++ sum].y = x;
s[sum].ne = head[y];
head[y] = sum;
} void dfs(int f,int fath)
{
depth[f] = depth[fath] + 1;
fa[f][0] = fath;
for(register int i = 1;(1 << i) <= depth[f];++ i)
fa[f][i] = fa[fa[f][i - 1]][i - 1];
for(int i = head[f];i != 0;i = s[i].ne)
if(s[i].y != fath)
dfs(s[i].y,f);
} int lca(int x,int y)
{
if(depth[x] < depth[y])swap(x,y);
for(register int i = 22;i >= 0;i --)
if(depth[fa[x][i]] >= depth[y])
x = fa[x][i];
if(x == y)return x;
for(register int i = 22;i >= 0;i --)
if(fa[x][i] != fa[y][i])
x = fa[x][i],y = fa[y][i];
return fa[x][0];
} /*
void doit(int x)
{
ans[x] = c[x];
while(fa[x][0] != 0)
{
ans[fa[x][0]] += ans[x] + a[fa[x][0]];
x = fa[x][0];
}
} void search(int x)
{
int js = 0;
for(register int i = head[x];i != 0;i = s[i].ne)
{
int qwq = s[i].y;
if(qwq != fa[x][0])
{
js ++;
ans[qwq] = ans[x] + c[qwq];
search(qwq);
}
}
if(js == 0)
doit(x);
}
*/ int search(int x)
{
ans[x] = c[x];
for(register int i = head[x];i != 0;i = s[i].ne)
{
int qwq = s[i].y;
if(qwq != fa[x][0])
ans[x] += search(qwq);
}
return ans[x];
}
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
int n;
cin >> n;
int x,y;
for(register int i = 1;i <= n;++ i)
cin >> a[i];
for(register int i = 1;i < n;++ i)
cin >> x >> y,add(x,y);
dfs(1,0);
//fa[1][0] = 1;
for(register int i = 1;i < n;++ i)
{
int LCA = lca(a[i],a[i + 1]);
c[LCA] -= 1;c[fa[LCA][0]] -= 1;
c[a[i]] ++;c[a[i + 1]] ++;
}
/*
for(int i = 1;i <= n;++ i)
cout << c[i] << endl;
*/
int acioi = search(1);
for(register int i = 1;i <= n;++ i)
{
if(i == a[1])
cout << ans[i] << endl;
else
cout << ans[i] - 1<< endl;
}
return 0;

最新文章

  1. 15款帮助你实现响应式导航的 jQuery 插件
  2. tesseract api C++使用例子
  3. 怎么直接让火狐输入json数据,而不是弹出文件保存对话框?
  4. python基础——迭代
  5. Map Columns From Different Tables and Create Insert and Update Statements in Oracle Forms
  6. CALayer实现遮罩效果
  7. SGU107——987654321 problem
  8. [cocos2d-x3.0]Android+NDK+Eclipse环境搭建及编译步骤~
  9. java项目组会议纪要
  10. VMWare网络设置的3中方式(转)
  11. winhec
  12. 【转载】Linux时间相关结构与函数
  13. Luogu P1860 新魔法药水
  14. ajax的原理解析
  15. Activtiy完全解析(二、layout的inflate过程)
  16. 《尚学堂_史上最易懂的设计模式视频》--章节5 动态代理-JDK6自带的编译器
  17. creator rotationY的问题
  18. JDBC复习2
  19. 051 Kafka的安装
  20. 使用组件构建Android应用程序

热门文章

  1. go 学习笔记(4) import
  2. 二分法在JavaScript中的应用实例
  3. pytorch learning rate decay
  4. 【洛谷 P2597】 [ZJOI2012]灾难(LCA)
  5. MQ相关
  6. HTTP2协议主要改进点
  7. org.springframework.dao.DuplicateKeyException: 问题
  8. 【scala】scala安装测试
  9. git如何删除已经提交的文件夹
  10. 传统Dolev-Yao攻击模型和eCK强安全模型之间的辨析