原题传送门

题意:给你一棵树,然后有一个遍历顺序,你需要补全这个遍历顺序,然后输出这个遍历顺序中每个点的出现次数。

解题思路:本来想找树剖的题,结果发现了一题可以直接写lca的。。。。

做法1:非常简单的NOIP式做法就是tjlca后直接树上差分即可。时间效率\( O(n) \)(常数较大).(BZOJ上1064ms)

#include <stdio.h>
#include <string.h>
#define MN 300005
#define v edge[i].to
struct link{int to,nxt;}edge[MN<<];
int cf[MN],h[MN],q[MN],a[MN],n,cnt,lca[MN],fa[MN],f[MN];
inline int in(){
int x=;bool f=; char ch=getchar();
while(ch<''||ch>'') f=ch=='-',ch=getchar();
while(ch>=''&&ch<='') x=(x<<)+(x<<)+ch-'',ch=getchar();
return f?-x:x;
}
inline void ins(int *h,int x,int y){edge[++cnt].to=y,edge[cnt].nxt=h[x],h[x]=cnt;}
inline void insw(int x,int y){ins(h,x,y);ins(h,y,x);}
inline int getfa(int x){return fa[x]?fa[x]=getfa(fa[x]):x;}
inline void tjlca(int u){
for (register int i=h[u]; i; i=edge[i].nxt)
if (v!=f[u]) f[v]=u,tjlca(v),fa[v]=u;
for (register int i=q[u]; i; i=edge[i].nxt)
if (lca[v]) lca[v]=getfa(lca[v]);
else lca[v]=u;
}
inline void dfs(int u){
for (register int i=h[u]; i; i=edge[i].nxt)
if (v!=f[u]) dfs(v),cf[u]+=cf[v];
}
void init(){
n=in();for (int i=; i<=n; ++i) a[i]=in(),ins(q,a[i],i),ins(q,a[i],i-);
for (register int i=; i<n; ++i) insw(in(),in());
}
void solve(){
tjlca();for (register int i=; i<n; ++i)
++cf[a[i]],++cf[a[i+]],--cf[lca[i]],--cf[f[lca[i]]];dfs();
for (register int i=; i<=n; ++i) --cf[a[i]];
for (register int i=; i<=n; ++i) printf("%d\n",cf[i]);
}
int main(){init(); solve(); return ;}

做法2:用树剖代替lca,用差分序列维护剖下来的树,也可以直接AC。时间效率为\( O(n \log \log n)\) ~\(O(n \log n) \)。(BZOJ 792ms)

#include <stdio.h>
#define MN 300005
int cnt,to[MN<<],nxt[MN<<];
int head[MN],siz[MN],son[MN],dep[MN],a[MN],top[MN],fa[MN],pos[MN],n,d[MN],dfsn;
inline int in(){
int x=;bool f=; char ch=getchar();
while(ch<''||ch>'') f=ch=='-',ch=getchar();
while(ch>=''&&ch<='') x=(x<<)+(x<<)+ch-'',ch=getchar();
return f?-x:x;
}
inline void ins(int x,int y){to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;}
inline void insw(int x,int y){ins(x,y);ins(y,x);};
inline void swp(int &a,int &b){a^=b^=a^=b;}
inline void dfs1(int u,int f,int d){
siz[u]=,fa[u]=f,dep[u]=d;
for (register int i=head[u]; i; i=nxt[i])
if (to[i]!=f){
dfs1(to[i],u,d+);siz[u]+=siz[to[i]];
if (siz[to[i]]>siz[son[u]]) son[u]=to[i];
}
}
inline void dfs2(int u,int tp){
top[u]=tp,pos[u]=(++dfsn);if (son[u]) dfs2(son[u],tp);
for (register int i=head[u]; i; i=nxt[i])
if (to[i]!=fa[u]&&to[i]!=son[u]) dfs2(to[i],to[i]);
}
inline void update(int x,int y){
while(top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swp(x,y);
++d[pos[top[x]]],--d[pos[x]+];x=fa[top[x]];
}if (dep[x]>dep[y]) swp(x,y);++d[pos[x]],--d[pos[y]+];
}
void init(){
n=in();for (register int i=; i<=n; ++i) a[i]=in();
for (register int i=; i<n; ++i) insw(in(),in());
dfs1(,,);dfs2(,);
}
void solve(){
for (register int i=; i<n; ++i) {
update(a[i],a[i+]);
if (i!=) --d[pos[a[i]]],++d[pos[a[i]]+];
}--d[pos[a[n]]],++d[pos[a[n]]+];
for (register int i=; i<=n; ++i) d[i]+=d[i-];
for (register int i=; i<=n; ++i)
printf("%d\n",d[pos[i]]);
}
int main(){init(); solve(); return ;}

【BZOJ3631】【JLOI2014】松鼠的新家的更多相关文章

  1. [Bzoj3631][JLOI2014]松鼠的新家 (树上前缀和)

    3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2350  Solved: 1212[Submit][Sta ...

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

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

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

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

  4. [BZOJ3631][JLOI2014]松鼠的新家(树链剖分)

    [BZOJ3631] 树剖模板题了, Code #include <cstdio> #include <algorithm> #define MID int mid=(l+r) ...

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

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

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

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

  7. BZOJ3631[JLOI2014]松鼠的新家 题解

    题目大意: 给你一棵树,要从编号为a[1]的节点走到编号为a[2]的节点再走到编号为a[3]的节点……一直走到编号为a[n]的节点.问每个节点最少访问多少次. 思路: 将其进行轻重链剖分,则从a[i] ...

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

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

  9. 【树链剖分】【树状数组】【最近公共祖先】【块状树】bzoj3631 [JLOI2014]松鼠的新家

    裸题,树状数组区间修改+单点查询.当然要稍微讨论一下链的左右端点是否修改的情况咯. #include<cstdio> #include<algorithm> #include& ...

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

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

随机推荐

  1. 多线程socket UDP收发数据

    多线程socket收发数据 from threading import Thread from socket import * def sendData(): while True: sendInfo ...

  2. 【Fungus入门】10分钟快速构建Unity中的万能对话系统 / 叙事系统 / 剧情系统

    我真的很久没有写过一个完整的攻略了(笑),咸鱼了很久之后还是想来写一个好玩的.这次主要是梳理一下Unity的小众插件Fungus的核心功能,并且快速掌握其使用方法. 官方文档:http://fungu ...

  3. windows 10下通过python3.6成功搭建jupyter 服务器

    最近通过python学习爬虫技术,发现一个工具jupyter notebook很不错,该工具明显优势通过浏览器可以输入多行python代码,支持在线运行以及运行结果保存功能,在线验证python小模块 ...

  4. DNS搜索过程

    以www.renyi.com为例 一:客户端首先检查本地HOST文件,是否有对应的IP地址,如果有,客户端直接访问,如果没有,则执行下一步. 二:客户端查看本地缓存信息,是否有对应的IP地址,如果有, ...

  5. python 内置函数之lambda-filter-reduce-apply-map

    (1)lambda lambda是Python中一个很有用的语法,它允许你快速定义单行最小函数.类似于C语言中的宏,可以用在任何需要函数的地方. 基本语法如下: 函数名 = lambda args1, ...

  6. print 函数设置字体颜色

    格式:\033[显示方式;前景色;背景色m数值表示的参数含义:显示方式: 0(默认值).1(高亮).22(非粗体).4(下划线).24(非下划线). 5(闪烁).25(非闪烁).7(反显).27(非反 ...

  7. 以太坊挖矿源码:clique算法

    上文我们总结了以太坊最主要的共识算法:ethash算法,本文将重点分析以太坊的另一个共识算法:clique. 关键字:clique,共识算法,puppeth,以太坊地址原理,区块校验,认证结点,POA ...

  8. maven常见问题处理(3-2)maven打包时跳过测试的几个方法

    运行mvn install时跳过Test方法一:<project> [...] <build> <plugins> <plugin> <group ...

  9. WebStorm2018破解

    参考网站http://www.sdbeta.com/wg/2018/0302/220048.html修改整理如下: webstorm 2018.1正式版破解summary jetbrainscrack ...

  10. SpringBoot2.x开发案例之整合Quartz任务管理系统

    基于spring-boot 2.x + quartz 的CRUD任务管理系统,适用于中小项目. 基于spring-boot +quartz 的CRUD任务管理系统: https://gitee.com ...