原题传送门

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

解题思路:本来想找树剖的题,结果发现了一题可以直接写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. 在深度linux下安装pip3与jupyter

    前言 以下安装说明基于已经正确安装python3 文件下载 https://pypi.python.org/pypi/pip 下载pip-9.0.1.tar.gz (md5, pgp)文件 安装准备工 ...

  2. tornado web高级开发项目

    抽屉官网:http://dig.chouti.com/ 一.配置(settings) settings = { 'template_path': 'views', #模板文件路径 'static_pa ...

  3. 《高级软件测试》JIRA使用手册(一)JIRA基本情况

    JIRA 官方网站为:https://www.atlassian.com/software/jira 中文代理网站为:https://www.jira.cn 现版本:v7.3.0 Atlassian公 ...

  4. centos 6.5安装并配置mysql

    折腾了半天终于把mysql安装并配置好了,以下是安装步骤和遇到问题的解决方式 1.查看机器上是否已经安装了mysql或其相关项 # yum list installed | grep mysql如果安 ...

  5. C语言Linix服务器网络爬虫项目(一)项目初衷和网络爬虫概述

    一.项目初衷和爬虫概述 1.项目初衷 本人的大学毕设就是linux上用c写的一个爬虫,现在我想把它完善起来,让他像一个企业级别的项目.为了重复发明轮子来学习轮子的原理,我们不使用第三方框架(这里是说的 ...

  6. threadlocal原理及常用应用场景

    1.深入解析ThreadLocal类 ThreadLocal类提供的几个方法: public T get() { } public void set(T value) { } public void  ...

  7. docker注意事项

      当你最后投入容器的怀抱,发现它能解决很多问题,而且还具有众多的优点: 第一:它是不可变的 – 操作系统,库版本,配置,文件夹和应用都是一样的.您可以使用通过相同QA测试的镜像,使产品具有相同的表现 ...

  8. apigw鉴权分析(1-3)百度 AI - 鉴权方式分析

    http://ai.baidu.com/docs#/Begin/top 一.访问入口 二.鉴权方式分析 1.鉴权认证方式一 - access_token - 针对HTTP API调用者 2.鉴权认证方 ...

  9. java实现两个int数交换

    普通方法,进阶方法,大神方法 @Test public void test3(){ int m = 5; int n = 12; //要求m和n交换位置 System.out.println(&quo ...

  10. EasyUI中datagrid的基本用法

    EasyUI中datagrid是最常用的一个控件了,现在整理一下datagrid的基本语法,先展示下页面效果吧,如下图