Description
松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
可是这样会导致维尼重复走很多房间,懒惰的维尼不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。维尼是个馋家伙,立马就答应了。
现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。
Input
第一行一个整数n,表示房间个数
第二行n个整数,依次描述a1-an
接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。
Output
一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让维尼有糖果吃。
题解
裸的树链剖分(看到PoPoQQQ巨神吐槽这道题太简单,我要是省选遇到这种题都笑开心死了。。。)
不会树链剖分的去这里学一学
区间加搞完后要将除了出发点的每个点的值-1。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 300010
using namespace std;
struct node{int to,next;}e[N*2];
int head[N],m;
int size[N],son[N],fa[N],top[N],tid[N],dep[N];
int n,tim,a[N];
void init() {
m = tim = 0;
memset(head,0,sizeof(head));
memset(son,-1,sizeof(son));
}
void add_edge(int from,int to) {
e[++m].next = head[from];
head[from] = m;
e[m].to = to;
}
void dfs1(int v,int pa,int d)
{
size[v] = 1; dep[v] = d; fa[v] = pa;
for(int i = head[v];i;i=e[i].next)
if(e[i].to != pa)
{
dfs1(e[i].to,v,d+1);
size[v] += size[e[i].to];
if(son[v] == -1 || size[e[i].to] > size[son[v]])
son[v] = e[i].to;
}
}
void dfs2(int v,int tp)
{
top[v] = tp; tid[v] = ++tim;
if(son[v] == -1) return;
dfs2(son[v],tp);
for(int i = head[v];i;i=e[i].next)
if(e[i].to != fa[v] && e[i].to != son[v])
dfs2(e[i].to,e[i].to);
}
#define lson o << 1
#define rson o << 1 | 1
int sum[N << 2],add[N << 2];
void build(int o,int l,int r)
{
add[o] = 0;
if(l == r){sum[o] = 0;return;}
int mid = (l+r)>>1;
build(lson,l,mid); build(rson,mid+1,r);
}
void pushdown(int o,int l,int r)
{
if(add[o] > 0) {
int mid = (l+r)>>1;
add[lson] += add[o]; sum[lson] += (mid-l+1)*add[o];
add[rson] += add[o]; sum[rson] += (r-mid)*add[o];
add[o] = 0;
}
}
void update(int o,int l,int r,int ll,int rr)
{
if(ll <= l && rr >= r) {
add[o] ++;
sum[o] += (r-l+1);
return;
}
pushdown(o,l,r);
int mid = (l+r)>>1;
if(ll <= mid) update(lson,l,mid,ll,rr);
if(rr > mid) update(rson,mid+1,r,ll,rr);
sum[o] = sum[lson] + sum[rson];
}
void change(int x,int y)
{
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x,y);
update(1,1,n,tid[top[x]],tid[x]);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x,y);
update(1,1,n,tid[x],tid[y]);
}
int query(int o,int l,int r,int pos)
{
if(l == r) return sum[o];
int mid = (l+r)>>1;
pushdown(o,l,r);
if(pos <= mid) return query(lson,l,mid,pos); else return query(rson,mid+1,r,pos);
}
int main()
{
int u,v;
scanf("%d",&n);
for(int i = 1;i <= n;i++) scanf("%d",&a[i]);
init();
for(int i = 1;i < n;i++) {
scanf("%d%d",&u,&v);
add_edge(u,v); add_edge(v,u);
}
dfs1(1,0,0);
dfs2(1,1);
build(1,1,n);
for(int i = 2;i <= n;i++) change(a[i-1],a[i]);
for(int i = 1;i <= n;i++) {
u = query(1,1,n,tid[i]);
if(i != a[1]) u--;
printf("%d\n",u);
}
return 0;
}