3631: [JLOI2014]松鼠的新家


Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2350  Solved: 1212
[Submit][Status][Discuss]

Description


松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
可是这样会导致维尼重复走很多房间,懒惰的维尼不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。维尼是个馋家伙,立马就答应了。
现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。

Input


第一行一个整数n,表示房间个数
第二行n个整数,依次描述a1-an
接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。

Output


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

Sample Input



Sample Output



HINT


2<= n <=300000

分析:


今天做了noip2015 day2 t3,发现这道省选题竟然是它的简化版。。。。。。。。

道理一样求树上前缀和,以第一个访问的为根,求出dfs序(每个点的st和en)和lca。

对于每一个访问的点u,和前一个点pre在前缀和数组里 +1,他们的lca -2.

这样对于除了根节点以外的所有点,他们的起始位置到结尾位置的和就为那条边经过的次数。(这个用前缀和O(n)处理,每次求一个点只用sum[en] - sum[st - 1]就可以了)。

对于每条边出现次数x,两端的点答案各加x/2,如果为奇数深度更深的那个点答案再加1

根节点最后要加一,最后位置要减1,其实比noip那道题还简单。。。。。

AC代码:


# include <iostream>
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <algorithm>
using namespace std;
const int N = 3e5 + ;
int head[N],cnt,n,lg,maxn;
int fa[N][],dep[N],vis[N];
struct Edge{
int to,next;
}edge[N << ];
void AddEdge(int u,int v){
Edge E = {v,head[u]};
edge[++cnt] = E;head[u] = cnt;
}
int st[N],en[N];
long long ans[N],sum[N];
void dfs(int u,int pre){
st[u] = ++cnt;
for(int i = head[u];i;i = edge[i].next){
int v = edge[i].to;
if(v == pre)continue;
fa[v][] = u;
dep[v] = dep[u] + ;
dfs(v,u);
}
maxn = max(maxn,dep[u]);
en[u] = cnt;
}
int lca(int x,int y){
if(dep[x] < dep[y])swap(x,y);
for(int i = lg;i >= ;i--){
if(dep[x] - ( << i) >= dep[y])x = fa[x][i];
}
for(int i = lg;i >= ;i--){
if((dep[x] - ( << i)) && fa[x][i] != fa[y][i]){
x = fa[x][i];
y = fa[y][i];
}
}
if(x != y)x = fa[x][];
return x;
}
int main(){
scanf("%d",&n);
int x,y,root;
for(int i = ;i <= n;i++){
scanf("%d",&vis[i]);
}
root = vis[];
for(int i = ;i < n;i++){
scanf("%d %d",&x,&y);
AddEdge(x,y);
AddEdge(y,x);
}
cnt = ;
dep[root] = maxn = ;
dfs(root,-);
int pre = root;
for(lg = ;( << lg) <= maxn;lg++);lg--;
for(int j = ;j <= lg;j++){
for(int i = ;i <= n;i++){
fa[i][j] = fa[fa[i][j - ]][j - ];
}
}
for(int i = ;i <= n;i++){
sum[st[vis[i]]]++;sum[st[pre]]++;
sum[st[lca(vis[i],pre)]] -= ;
pre = vis[i];
}
for(int i = ;i <= n;i++){
sum[i] += sum[i - ];
}
long long z;
for(int i = ;i <= n;i++){
z = sum[en[i]] - sum[st[i] - ];
if(z & 1LL){
ans[i]++;
}
ans[i] += z / 2LL;ans[fa[i][]] += z / 2LL;
}
ans[pre]--;ans[root]++;
for(int i = ;i <= n;i++){
printf("%lld\n",ans[i]);
}
}

[Bzoj3631][JLOI2014]松鼠的新家 (树上前缀和)的更多相关文章

  1. bzoj3631 [JLOI2014]松鼠的新家——树上差分

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3631 树上差分:注意路径的结尾被多算了一次,最后要减去(不能提前减). 代码如下: #inc ...

  2. BZOJ3631 [JLOI2014]松鼠的新家 【树上差分】

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

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

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

  4. BZOJ 3631: [JLOI2014]松鼠的新家 树上差分 + LCA

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

  5. bzoj3631: [JLOI2014]松鼠的新家(树上差分)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3631 题目大意:给定含有n个顶点的树,给定走遍整棵树顺序的序列a[1],a[2],a[3 ...

  6. bzoj3631: [JLOI2014]松鼠的新家(LCA+差分)

    题目大意:一棵树,以一定顺序走完n个点,求每个点经过多少遍 可以树链剖分,也可以直接在树上做差分序列的标记 后者打起来更舒适一点.. 具体实现: 先求x,y的lca,且dep[x]<dep[y] ...

  7. BZOJ3631: [JLOI2014]松鼠的新家

    传送门 树上的差分优化,很简单的一道题,应该属于NOIP2015TGD2T3的子问题. //BZOJ 3631 //by Cydiater //2016.10.25 #include <iost ...

  8. bzoj3631[JLOI2014 松鼠的新家 倍增lca+差分

    裸的树上差分+倍增lca 每次从起点到终点左闭右开,这就有一个小技巧,要找到右端点向左端点走的第一步,然后差分就好了 #include<cstdio> #include<cstrin ...

  9. [JLOI2014]松鼠的新家 树上差分

    差分 一开始竟然想分情况讨论来差分,然后发现各自情况要分析, 就是为了解决中间节点重复计算的问题, 结果 最后一想,中间重复计算了一次,那我最后减掉不就好了么,,, 那这就是一道差分裸题了(这是唯一不 ...

随机推荐

  1. SQLServer · 最佳实践 · SQL Server 2012 使用OFFSET分页遇到的问题

    1. 背景 最近有一个客户遇到一个奇怪的问题,以前使用ROW_NUMBER来分页结果是正确的,但是替换为SQL SERVER 2012的OFFSET...FETCH NEXT来分页出现了问题,因此,这 ...

  2. COGS 1361. 树

    ★   输入文件:treed.in   输出文件:treed.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 在一个凉爽的夏夜,xth和rabbit来到花园里砍树.为啥 ...

  3. Unity3D_最简单的开始界面_结束界面

    开始界面1.创建一个新的场景添加button 2.C#脚本LoadingGame.cs using System.Collections;using System.Collections.Generi ...

  4. centos下安装nodejs的三种种方式

    方法一:源码包安装 官网下载 centos下载最新版10.9 https://nodejs.org/dist/v10.9.0/node-v10.9.0-linux-x64.tar.xz mkdir / ...

  5. windwos .bat脚本大全

    记录一个很有用比较全面的windows .bat脚本网站 https://www.cnblogs.com/zhaoqingqing/p/4620402.html

  6. 利用canvas写一个验证码小功能

    刚刚开始接触canvas,写个验证码小功能练练手,实现效果图如下: 主要代码如下: html <!DOCTYPE html> <html lang="en"> ...

  7. c++的if语句中的110为什么不等于110?

    从上图可以看出,当表达式1.1*x被直接放进if的判断括号中时1.1*x不等于y,但是将1.1*x赋值给z时,z与y相等,这是为什么?(以下为不等价时的代码) #include<stdio.h& ...

  8. MySQL安装示例数据库

    MySQL安装示例数据库 本文档演示如何下载及安装MySQL示例数据库sakila及employees数据库 1. 安装sakila数据库 1.1 下载sakila数据库 wget http://do ...

  9. js多维数组扁平化

    数组扁平化,就是将多维数组碾平为一维数组,方便使用. 一:例如,一个二维数组 var arr = ['a', ['b', 2], ['c', 3, 'x']],将其扁平化: 1.  通过 apply ...

  10. OAuth2.0授权流程

    微信授权 第3步的微信授权中的scope字段: snsapi_base 静默授权,不弹出用户同意框,可直接获取成员的基础信息:    snsapi_userinfo:静默授权,弹出用户同意框,待用户同 ...