【BZOJ3631】【JLOI2014】松鼠的新家
题意:给你一棵树,然后有一个遍历顺序,你需要补全这个遍历顺序,然后输出这个遍历顺序中每个点的出现次数。
解题思路:本来想找树剖的题,结果发现了一题可以直接写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】松鼠的新家的更多相关文章
- [Bzoj3631][JLOI2014]松鼠的新家 (树上前缀和)
3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2350 Solved: 1212[Submit][Sta ...
- BZOJ3631 [JLOI2014]松鼠的新家 【树上差分】
题目 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在"树"上.松鼠想 ...
- [BZOJ3631]:[JLOI2014]松鼠的新家(LCA+树上差分)
题目传送门 题目描述: 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀 ...
- [BZOJ3631][JLOI2014]松鼠的新家(树链剖分)
[BZOJ3631] 树剖模板题了, Code #include <cstdio> #include <algorithm> #define MID int mid=(l+r) ...
- bzoj3631: [JLOI2014]松鼠的新家(LCA+差分)
题目大意:一棵树,以一定顺序走完n个点,求每个点经过多少遍 可以树链剖分,也可以直接在树上做差分序列的标记 后者打起来更舒适一点.. 具体实现: 先求x,y的lca,且dep[x]<dep[y] ...
- BZOJ3631: [JLOI2014]松鼠的新家
传送门 树上的差分优化,很简单的一道题,应该属于NOIP2015TGD2T3的子问题. //BZOJ 3631 //by Cydiater //2016.10.25 #include <iost ...
- BZOJ3631[JLOI2014]松鼠的新家 题解
题目大意: 给你一棵树,要从编号为a[1]的节点走到编号为a[2]的节点再走到编号为a[3]的节点……一直走到编号为a[n]的节点.问每个节点最少访问多少次. 思路: 将其进行轻重链剖分,则从a[i] ...
- bzoj3631[JLOI2014 松鼠的新家 倍增lca+差分
裸的树上差分+倍增lca 每次从起点到终点左闭右开,这就有一个小技巧,要找到右端点向左端点走的第一步,然后差分就好了 #include<cstdio> #include<cstrin ...
- 【树链剖分】【树状数组】【最近公共祖先】【块状树】bzoj3631 [JLOI2014]松鼠的新家
裸题,树状数组区间修改+单点查询.当然要稍微讨论一下链的左右端点是否修改的情况咯. #include<cstdio> #include<algorithm> #include& ...
- bzoj3631 [JLOI2014]松鼠的新家——树上差分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3631 树上差分:注意路径的结尾被多算了一次,最后要减去(不能提前减). 代码如下: #inc ...
随机推荐
- Python 实现双端队列 Deque
操作 Deque() 创建一个空的双端队列 add_front(item) 从队头加入一个item元素 add_rear(item) 从队尾加入一个item元素 remove_front() 从队头删 ...
- 201421123042 《Java程序设计》第10周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1. 常用异常 结合题集题目7-1回答 1.1 自己以前编写的代码中经常出现 ...
- 洛谷 U10783 名字被和谐了
https://www.luogu.org/problem/show?pid=U10783 题目背景 众所周知,我们称g是a的约数,当且仅当g是正数且a mod g = 0. 众所周知,若g既是a的约 ...
- WPF自学入门(十)WPF MVVM简单介绍
前面文章中,我们已经知道,WPF技术的主要特点是数据驱动UI,所以在使用WPF技术开发的过程中是以数据为核心的,WPF提供了数据绑定机制,当数据发生变化时,WPF会自动发出通知去更新UI. 我们不管 ...
- easyUI combobox 添加空白项
今天测试反馈了一个问题,希望可以在下拉框下面加一个空白的选项(下拉框用的是combobox方法). 开始分析这个问题: 首先,这个数据都是后台读出来的,那么我在后台直接添加可以么,答案是可以的,如果没 ...
- c# windows service 实现监控其他程序是否被关闭,关闭则报警
namespace MonitorService { public partial class MonitorSv : ServiceBase { string AppName = "&qu ...
- Linux背景知识(1)RedHat和Centos
Redhat有收费的商业版和免费的开源版,商业版的业内称之为RHEL(Red Hat Enterprise Linux)系列, 而这个CentOS(Community ENTerprise Opera ...
- nginx反向代理二级域名注意事项
摘要 本文介绍了利用nginx实现多域名和多站点的绑定的方法及相关注意事项.您也可以只看本文的标题或红色标注部分.☺ 1.应用场景 我们经常会遇到在同一台服务器建立多个Web站点的情况,普遍的做法是为 ...
- ECSHOP模板 蘑菇街2018广告楼层设置说明
楼层广告以及说明 图1 ------------------ 设置,通过,后台,模板设置,分类下的商品,选用需要显示的商品分类 图2------------------ 后台,编辑商品分类的广告链接. ...
- day3 自定义指令详解
在angular中,Directive,自定义指令的学习,可以更好的理解angular指令的原理,当angular的指令不能满足你的需求的时候,嘿嘿,你就可以来看看这篇文章,自定义自己的指令,可以满足 ...