[bzoj 3631--JLOI2014]松鼠的新家
2018-03-22 10:52
603 查看
松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
可是这样会导致维尼重复走很多房间,懒惰的维尼不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。维尼是个馋家伙,立马就答应了。
现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。
这道题用树剖直接可以做,但是想用一个代码复杂度小的方法。如果学过树上差分的同学就会知道,这道题是一种基本思路,对点进行修改。修改操作时只需让s[l]++,s[r]++,s[lca]–,s[f[lca][0]]–,询问操作时,只需算出它的总子树的s和。为什么呢,%一下它。
可是这样会导致维尼重复走很多房间,懒惰的维尼不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。维尼是个馋家伙,立马就答应了。
现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。
这道题用树剖直接可以做,但是想用一个代码复杂度小的方法。如果学过树上差分的同学就会知道,这道题是一种基本思路,对点进行修改。修改操作时只需让s[l]++,s[r]++,s[lca]–,s[f[lca][0]]–,询问操作时,只需算出它的总子树的s和。为什么呢,%一下它。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; struct node { int x,y,next; }a[650010];int len,last[350010]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } long long f[350010][22],dep[350010],sx[350010]; long long ss[350010]; void dfs1(int x) { for(int i=1;i<=19;i++)f[x][i]=f[f[x][i-1]][i-1]; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=f[x][0]) { f[y][0]=x; dep[y]=dep[x]+1; dfs1(y); } } } int LCA(int x,int y) { if(dep[x]<dep[y])swap(x,y); for(int i=19;i>=0;i--) { if((dep[x]-dep[y])>=(1<<i))x=f[x][i]; } if(x==y)return x; for(int i=19;i>=0;i--) { if(dep[x]>=(1<<i) && f[x][i]!=f[y][i]) { x=f[x][i];y=f[y][i]; } } return f[x][0]; } void dfs2(int x) { for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=f[x][0]) { dfs2(y); ss[x]+=ss[y]; } } } int main() { int n; scanf("%lld",&n); for(int i=1;i<=n;i++)scanf("%lld",&sx[i]); for(int i=1;i<n;i++) { long long x,y; scanf("%lld%lld",&x,&y); ins(x,y);ins(y,x); } dfs1(sx[1]); for(int i=1;i<n;i++) { int x=sx[i],y=sx[i+1]; ss[x]++;ss[y]++; int lca=LCA(x,y); ss[lca]--;ss[f[lca][0]]--; } dfs2(sx[1]); for(int i=2;i<=n;i++)ss[sx[i]]--; for(int i=1;i<=n;i++)printf("%lld\n",ss[i]); return 0; }
相关文章推荐
- BZOJ 3631 JLOI2014 松鼠的新家 树链剖分/LCA
- BZOJ3631 [JLOI2014]松鼠的新家(树链剖分)
- [BZOJ3631] [JLOI2014] 松鼠的新家
- 【BZOJ3631】[JLOI2014]松鼠的新家 树链剖分
- 【bzoj 3631】[JLOI2014]松鼠的新家(树链剖分)
- bzoj 3631: [JLOI2014]松鼠的新家 树链剖分
- [BZOJ3631]JLOI2014松鼠的新家|树上差分
- Bzoj 3631: [JLOI2014]松鼠的新家(树链剖分+线段树)
- [BZOJ] 3631: [JLOI2014]松鼠的新家
- 洛谷 P3258 BZOJ 3631 [JLOI2014]松鼠的新家
- BZOJ3631[JLOI2014]松鼠的新家 题解
- bzoj 3631: [JLOI2014]松鼠的新家
- BZOJ 3631 [JLOI2014]松鼠的新家==树剖
- 【树链剖分】【树状数组】【最近公共祖先】【块状树】bzoj3631 [JLOI2014]松鼠的新家
- [Bzoj3631][JLOI2014]松鼠的新家 (树上前缀和)
- BZOJ 3631 JLOI 2014 松鼠的新家 LCA 树链剖分
- bzoj3631: [JLOI2014]松鼠的新家 (树上差分)
- BZOJ3631 [JLOI2014] 松鼠的新家
- bzoj 3631: [JLOI2014]松鼠的新家
- 【BZOJ3631】【JLOI2014】松鼠的新家