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. Summary of 2016 International Trusted Computing and Cloud Security Summit

    1)      Welcome Remarks 2)      The advancement of Cloud Computing and Tursted Computing national st ...

  2. PMP项目管理学习笔记(12)——范围管理之创建工作分解结构(WBS)

    创建工作分解结构过程是范围管理知识领域中最重要的过程,因为要在此过程明确所要做的全部工作 输入:收集需求和定义范围过程的输出会成为创建工作分解结构过程的输入(需求文档.组织资产过程.项目范围说明书) ...

  3. TensorFlow低阶API(四)—— 图和会话

    简介 TensorFlow使用数据流图将计算表示为独立的指令之间的依赖关系.这可生成低级别的编程模型,在该模型中,您首先定义数据流图,然后创建TensorFlow会话,以便在一组本地和远程设备上运行图 ...

  4. node.js中使用Redis

    服务端: 启动Redis服务: redis-server 客户端: 1.安装Redis        npm install redis --save 2.redisTest.js文件 //引入red ...

  5. Oracle中的for和while循环

    实例: beginfor i in 51..500 loop delete from test t where t.date=to_date('2016-07-01', 'yyyy-MM-dd') a ...

  6. set指令详解

    set指令详解 功能说明:设置shell 语 法:set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...] 说 明:设置或取消设置shell选项 ...

  7. jQuery.data() 的实现方式

    jQuery.data() 的作用是为普通对象或 DOM Element 附加(及获取)数据. 下面将分三个部分分析其实现方式:     1. 用name和value为对象附加数据:即传入三个参数,第 ...

  8. 阿里巴巴集团加入W3C,成为W3C会员

    根据W3C官方推特最新消息:阿里巴巴集团正式加入W3C,成为W3C会员. W3C官方推特:https://twitter.com/w3c/status/566244180372889601 同时可以在 ...

  9. 【Codeforces 449A】Jzzhu and Chocolate

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 设最后行分成了x行,列分成了y列. 那么答案就是floor(n/x)floor(n/y) 然后x+y-2=k //即平均分配x行.y列 我们可 ...

  10. Google JavaScript代码风格指南

    Google JavaScript代码风格指南 修正版本 2.28 Aaron Whyte Bob Jervis Dan Pupius Eric Arvidsson Fritz Schneider R ...