题目描述

松鼠的新家是一棵树,前几天刚刚装修了新家,新家有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

题解

  我可能开了个假的优化……吸了氧一直RE第四个点……不吸竟然A了……

    考虑树上差分,用$val[i]$表示从根节点到$i$点的所有答案$+1$,那么每一个操作可以转化成如下

         int u=a[i],v=a[i+];
++val[u],++val[v];
int k=LCA(u,v);
--val[k],--val[fa[k]];

然后我们只要一遍dfs,让每个点的$val$加上子树的$val$之和即可

 //minamoto
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[<<],z[];int C=-,Z;
inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
inline void print(int x){
if(C><<)Ot();if(x<)sr[++C]=,x=-x;
while(z[++Z]=x%+,x/=);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=;
int ver[N<<],head[N],Next[N<<],tot;
int sz[N],dep[N],son[N],top[N],fa[N],val[N];
int a[N];
int n;
inline void add(int u,int v){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
ver[++tot]=u,Next[tot]=head[v],head[v]=tot;
}
void dfs1(int u){
dep[u]=dep[fa[u]]+,sz[u]=;
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=fa[u]){
fa[v]=u,dfs1(v),sz[u]+=sz[v];
if(sz[v]>sz[son[u]]) son[u]=v;
}
}
}
void dfs2(int u){
if(!top[u]) top[u]=u;
if(son[u]) top[son[u]]=top[u],dfs2(son[u]);else return;
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=fa[u]&&v!=son[u]) dfs2(v);
}
}
int LCA(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v]?u:v;
}
void dfs(int u){
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=fa[u]){
dfs(v),val[u]+=val[v];
}
}
}
int main(){
n=read();
for(int i=;i<=n;++i) a[i]=read();
for(int i=;i<n;++i){
int u=read(),v=read();add(u,v);
}
dfs1(),dfs2();
for(int i=;i<n;++i){
int u=a[i],v=a[i+];
++val[u],++val[v];
int k=LCA(u,v);
--val[k],--val[fa[k]];
}
dfs();
for(int i=;i<=n;++i) --val[a[i]];
for(int i=;i<=n;++i) print(val[i]);
Ot();
return ;
}

洛谷P3258 [JLOI2014]松鼠的新家(树上差分+树剖)的更多相关文章

  1. 洛谷 P3258 [JLOI2014]松鼠的新家 解题报告

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

  2. 洛谷P3258 [JLOI2014]松鼠的新家

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

  3. 洛谷 P3258 [JLOI2014]松鼠的新家 题解

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

  4. 洛谷 P3258 [JLOI2014]松鼠的新家 树链剖分+差分前缀和优化

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 说明 思路 AC代码 优化 优化后AC代码 总结 题面 题目链接 P3258 [JLOI2 ...

  5. 洛谷 P3258 [JLOI2014]松鼠的新家(树链剖分)

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

  6. 洛谷——P3258 [JLOI2014]松鼠的新家

    https://www.luogu.org/problem/show?pid=3258 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到 ...

  7. 洛谷 P3258 [JLOI2014]松鼠的新家

    树剖,裸题,鉴定完毕. 我是题面 读完题,恩,树剖,裸题,没劲. 处理很简单,既然每到一个房间吃一块糖,那么就在每条路径上的每个房间放一颗糖,但是每条路径的终点也就是下一条路径的起点,在这里只能加一次 ...

  8. 洛谷P3258 [JLOI2014]松鼠的新家【LCA+树上差分】

    简要题意 树上n个节点,给定路径,求每个点经过次数 题意分析 对于每两个点,有两种情况,第一种,他们的lca为本身,第二种,他们有公共祖先,又要求他们的点经过次数,暴力是不可能的,复杂度不对,所以可以 ...

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

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

随机推荐

  1. 机器学习:PCA(高维数据映射为低维数据 封装&调用)

    一.基础理解 1) PCA 降维的基本原理 寻找另外一个坐标系,新坐标系中的坐标轴以此表示原来样本的重要程度,也就是主成分:取出前 k 个主成分,将数据映射到这 k 个坐标轴上,获得一个低维的数据集. ...

  2. Regexp:教程

    ylbtech-Regexp:教程 1.返回顶部 1. 正则表达式 - 教程 正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符( ...

  3. 调试json

    console.log("======================") // 转对象 //var obj = eval('(' + data + ')'); // 转对象 // ...

  4. [Apache]架设Apache服务器

    我自己使用的是Ubuntu的操作系统, 所以我主要是记录的在ubuntu的Apache的安装和简单的配置. Apache服务器的架设: 一.命令行安装 使用下面的指令下载apache2 sudo ap ...

  5. JavaScript基本概念C - 真与假

    真与假 与 c 和 c++ 非常相似, 但与 Java 不同, JS中被认为true或false范围很广.所有对象 (空字符串除外) 和非零数字都被视为 true.空字符串.零.null 和undef ...

  6. mysql应用基本操作语句(转)

    二.库操作 1..创建数据库 命令:create database <数据库名> 例如:建立一个名为xhkdb的数据库 mysql> create database xhkdb; 2 ...

  7. Python 学习之---文件目录处理

    前言:有关文件夹与文件的查找,删除等功能 在 os 模块中实现.使用时需先导入这个模块, 导入的方法是:import os   一.取得当前目录 s = os.getcwd() s 中保存的是当前目录 ...

  8. 部署和调优 3.1 dns安装配置-1

    安装配置DNS服务器 装一个bind,首先搜一下. yum list |grep bind bind.x86_64   我们安装这个 安装 yum install bind.x86_64 -y 看一下 ...

  9. oracle系统函数(日期函数)

    oracle系统函数(日期函数) 调用日期函数时,首先要明确两个概念,时间戳和日期是不同的,日期中包括年月日但不包括小时分钟秒,时间戳包括年月日小时分钟秒.在oracle中,一般情况下,函数中包含da ...

  10. springmvc 注解式开发 解决中文乱码问题