BZOJ3631[JLOI2014]松鼠的新家 题解
2016-08-03 18:21
267 查看
题目大意:
给你一棵树,要从编号为a[1]的节点走到编号为a[2]的节点再走到编号为a[3]的节点……一直走到编号为a
的节点。问每个节点最少访问多少次。
思路:
将其进行轻重链剖分,则从a[i]走到a[i+1]实际上就是在几段重链的节点上+1,于是就用线段树来维护一下即可。
代码:
给你一棵树,要从编号为a[1]的节点走到编号为a[2]的节点再走到编号为a[3]的节点……一直走到编号为a
的节点。问每个节点最少访问多少次。
思路:
将其进行轻重链剖分,则从a[i]走到a[i+1]实际上就是在几段重链的节点上+1,于是就用线段树来维护一下即可。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 1200000 using namespace std; int ans[M],to[M],head[M],next[M],vis[M],size[M],deep[M],id[M],top[M],sum[M],fa[M],a[M],cnt,dfn,n; void add(int x,int y) { to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt; } void dfs1(int x) { size[x]=vis[x]=1; for (int i=head[x];i;i=next[i]) if (!vis[to[i]]) { deep[to[i]]=deep[x]+1; fa[to[i]]=x; dfs1(to[i]); size[x]+=size[to[i]]; } } void dfs2(int x,int chain) { int k=0,i; id[x]=++dfn; top[x]=chain; for (i=head[x];i;i=next[i]) if (deep[to[i]]>deep[x] && size[to[i]]>size[k]) k=to[i]; if (!k) return; dfs2(k,chain); for (i=head[x];i;i=next[i]) if (deep[to[i]]>deep[x] && to[i]!=k) dfs2(to[i],to[i]); } void push_down(int cur) { sum[cur<<1]+=sum[cur]; sum[cur<<1|1]+=sum[cur]; sum[cur]=0; } void ADD(int L,int R,int l,int r,int cur) { if (l<=L && r>=R) { sum[cur]++; return; } push_down(cur); int mid=L+R>>1; if (l>mid) ADD(mid+1,R,l,r,cur<<1|1); else if (r<=mid) ADD(L,mid,l,r,cur<<1); else ADD(L,mid,l,mid,cur<<1),ADD(mid+1,R,mid+1,r,cur<<1|1); } int ask(int l,int r,int x,int cur) { if (l==r) return sum[cur]; push_down(cur); int mid=l+r>>1; if (x>mid) return sum[cur]+ask(mid+1,r,x,cur<<1|1); else return sum[cur]+ask(l,mid,x,cur<<1); } void Add(int x,int y) { for (;top[x]!=top[y];x=fa[top[x]]) { if (deep[top[x]]<deep[top[y]]) swap(x,y); ADD(1,n,id[top[x]],id[x],1); } if (deep[x]<deep[y]) swap(x,y); ADD(1,n,id[y],id[x],1); } int main() { int i,x,y; scanf("%d",&n); for (i=1;i<=n;i++) scanf("%d",&a[i]); for (i=1;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x); dfs1(1); dfs2(1,1); for (i=1;i<n;i++) Add(a[i],a[i+1]); for (i=1;i<=n;i++) { ans[i]=-(i!=a[1]); ans[i]+=ask(1,n,id[i],1); } for (i=1;i<=n;i++) printf("%d\n",ans[i]); return 0; }
相关文章推荐
- BZOJ 3631 [JLOI2014]松鼠的新家
- BZOJ3631 [JLOI2014]松鼠的新家(树链剖分)
- bzoj 3631: [JLOI2014]松鼠的新家
- bzoj3631: [JLOI2014]松鼠的新家 (树上差分)
- [BZOJ3631] [JLOI2014] 松鼠的新家
- 【BZOJ3631】[JLOI2014]松鼠的新家 树链剖分
- BZOJ3631 [JLOI2014]松鼠的新家
- bzoj 3631: [JLOI2014]松鼠的新家
- [BZOJ3631]JLOI2014松鼠的新家|树上差分
- 【BZOJ】3631 [JLOI2014]松鼠的新家 LCA+树上差分
- Bzoj3631: [JLOI2014]松鼠的新家
- BZOJ 3631 [JLOI2014]松鼠的新家==树剖
- 【bzoj3631】[JLOI2014]松鼠的新家 LCA+差分数组
- bzoj3631[JLOI2014 松鼠的新家 倍增lca+差分
- BZOJ 3631: [JLOI2014]松鼠的新家【差分】【LCA】
- BZOJ3631 [JLOI2014]松鼠的新家 【树上差分】
- Bzoj3631: [JLOI2014]松鼠的新家
- BZOJ3631: [JLOI2014]松鼠的新家
- 【树链剖分】【树状数组】【最近公共祖先】【块状树】bzoj3631 [JLOI2014]松鼠的新家
- [BZOJ3631][洛谷P3258][JLOI2014]松鼠的新家