Description
松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
可是这样会导致维尼重复走很多房间,懒惰的维尼不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。维尼是个馋家伙,立马就答应了。
现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。
2<= n <=300000
Solution
很裸的树链剖分,注意一段路程的终点和上一段路程的起点会重复,要删掉一个
新年前的最后一题了吧。我比较弱,不敢打cf也做不出什么算马,但是我觉的coding真的很有趣很好玩。虽然有时候也会很累,但是看到自己的努力会有成果还是很开心的。通过竞赛认识了很多有趣的人,也希望可以一直走下去看更高处的风景
//hello2018
Code
//Hello 2018
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
#define fill(x,t) memset(x,t,sizeof(x))
using std:: swap;
const int INF=0x3f3f3f3f;
const int N=300005;
const int E=700005;
struct edge{int x,y,next;}e[E];
int ls[N],edCnt=0;
int lazy[N<<2],sum[N<<2],a[N];
int size[N],dep[N],pos[N],bl[N],fa[N];
int n;
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void addEdge(int x,int y) {
e[++edCnt]=(edge){x,y,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge){y,x,ls[y]}; ls[y]=edCnt;
}
void dfs1(int now,int father) {
size[now]=1;
for (int i=ls[now];i;i=e[i].next) {
if (e[i].y==father) continue;
dep[e[i].y]=dep[now]+1;
fa[e[i].y]=now;
dfs1(e[i].y,now);
size[now]+=size[e[i].y];
}
}
void dfs2(int now,int up) {
pos[now]=++pos[0];
bl[now]=up;
int mx=0;
for (int i=ls[now];i;i=e[i].next) {
if (dep[e[i].y]<=dep[now]||size[e[i].y]<=size[mx]) continue;
mx=e[i].y;
}
if (!mx) return ;
dfs2(mx,up);
for (int i=ls[now];i;i=e[i].next) {
if (dep[e[i].y]<=dep[now]||e[i].y==mx) continue;
dfs2(e[i].y,e[i].y);
}
}
void push_up(int now) {
sum[now]=sum[now<<1]+sum[now<<1|1];
}
void push_down(int now,int tl,int tr) {
if (!lazy[now]) return ;
int mid=(tl+tr)>>1;
sum[now<<1]+=(mid-tl+1)*lazy[now];
sum[now<<1|1]+=(tr-mid)*lazy[now];
lazy[now<<1]+=lazy[now];
lazy[now<<1|1]+=lazy[now];
lazy[now]=0;
}
int query(int now,int tl,int tr,int l,int r) {
if (tl==l&&tr==r) return sum[now];
push_down(now,tl,tr);
int mid=(tl+tr)>>1;
if (r<=mid) return query(now<<1,tl,mid,l,r);
else if (l>mid) return query(now<<1|1,mid+1,tr,l,r);
else return query(now<<1,tl,mid,l,mid)+query(now<<1|1,mid+1,tr,mid+1,r);
}
void modify(int now,int tl,int tr,int l,int r,int v) {
if (tl==l&&tr==r) {
sum[now]+=(tr-tl+1)*v;
lazy[now]+=v;
return ;
}
push_down(now,tl,tr);
int mid=(tl+tr)>>1;
if (r<=mid) modify(now<<1,tl,mid,l,r,v);
else if (l>mid) modify(now<<1|1,mid+1,tr,l,r,v);
else {
modify(now<<1,tl,mid,l,mid,v);
modify(now<<1|1,mid+1,tr,mid+1,r,v);
}
push_up(now);
}
void buildTree(int now,int tl,int tr) {
sum[now]=0;
if (tl==tr) return ;
int mid=(tl+tr)>>1;
buildTree(now<<1,tl,mid);
buildTree(now<<1|1,mid+1,tr);
}
void add_candy(int x,int y) {
while (bl[x]!=bl[y]) {
if (dep[bl[x]]<dep[bl[y]]) swap(x,y);
modify(1,1,n,pos[bl[x]],pos[x],1);
x=fa[bl[x]];
}
if (pos[x]>pos[y]) swap(x,y);
modify(1,1,n,pos[x],pos[y],1);
}
int main(void) {
n=read();
rep(i,1,n) a[i]=read();
rep(i,2,n) {
int x=read(),y=read();
addEdge(x,y);
}
buildTree(1,1,n);
dfs1(1,0);
dfs2(1,1);
rep(i,2,n) {
add_candy(a[i-1],a[i]);
modify(1,1,n,pos[a[i]],pos[a[i]],-1);
}
rep(i,1,n) printf("%d\n", query(1,1,n,pos[i],pos[i]));
return 0;
}