树链剖分
晚上神志不清的时候写的,头晕眼花si初值忘记赋了,导致变成了随机连剖分(丢人.....)
/**************************************************************
Problem: 3631
User: syh0313
Language: C++
Result: Accepted
Time:1828 ms
Memory:61640 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <string>
#define lch a[n].lc
#define rch a[n].rc
using
namespace
std;
const
int
maxn=400010;
int
n,ord[maxn],topt,to[maxn<<1],st[maxn<<1],nt[maxn<<1],root,cnt;
int
fa[maxn],rem[maxn],si[maxn],dep[maxn];
int
dfn[maxn],line[maxn],dfn_num,top[maxn];
long
long
ans[maxn];
bool
f[maxn];
struct
da{
int
lc,rc;
long
long
tag;}a[maxn<<2];
void
add(
int
x,
int
y)
{to[++topt]=y; nt[topt]=st[x]; st[x]=topt;}
void
dfs1(
int
x,
int
de)
{
f[x]=1; dep[x]=de; si[x]=1;
int
p=st[x],ma=0;
while
(p)
{
if
(!f[to[p]])
{
dfs1(to[p],de+1);
fa[to[p]]=x; si[x]+=si[to[p]];
if
(si[to[p]]>ma) {ma=si[to[p]]; rem[x]=to[p];}
}
p=nt[p];
}
}
void
dfs2(
int
x)
{
f[x]=1;
if
(rem[fa[x]]==x) top[x]=top[fa[x]];
else
top[x]=x;
dfn[x]=++dfn_num; line[dfn_num]=x;
if
(rem[x]) dfs2(rem[x]);
int
p=st[x];
while
(p)
{
if
(!f[to[p]]) dfs2(to[p]);
p=nt[p];
}
}
/*void build_tree(int &n,int l,int r)
{
n=++cnt; if (l==r) return;
int mid=(l+r)>>1;
build_tree(lch,l,mid); build_tree(rch,mid+1,r);
}
*/
void
tree_add(
int
&n,
int
L,
int
R,
int
l,
int
r)
{
if
(!n) n=++cnt;
if
(L==l && R==r) {a[n].tag++;
return
;}
int
mid=(L+R)>>1;
if
(r<=mid) tree_add(lch,L,mid,l,r);
else
if
(l>=mid+1) tree_add(rch,mid+1,R,l,r);
else
tree_add(lch,L,mid,l,mid),tree_add(rch,mid+1,R,mid+1,r);
}
void
tadd(
int
x,
int
y)
{
while
(top[x]!=top[y])
{
if
(dep[top[x]]<dep[top[y]]) swap(x,y);
tree_add(root,1,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if
(dfn[x]>dfn[y]) swap(x,y);
tree_add(root,1,n,dfn[x],dfn[y]);
}
void
qury(
int
&n,
int
l,
int
r,
long
long
k)
{
if
(!n) topt++;
if
(l==r) {ans[line[l]]=k;
return
;}
int
mid=(l+r)>>1;
qury(lch,l,mid,k+a[lch].tag);
qury(rch,mid+1,r,k+a[rch].tag);
}
int
read()
{
int
xx=0,ff=1;
char
c=
getchar
();
while
(c<
'0'
|| c>
'9'
) {
if
(c==
'-'
) ff=-1; c=
getchar
();}
while
(c>=
'0'
&& c<=
'9'
) {xx=(xx<<1)+(xx<<3)+c-
'0'
; c=
getchar
();}
return
xx*ff;
}
int
main()
{
//freopen("1.in","r",stdin);
n=read();
for
(
int
i=1;i<=n;i++) ord[i]=read();
for
(
int
i=1;i<n;i++)
{
int
xx,yy; xx=read(); yy=read();
add(xx,yy); add(yy,xx);
}
dfs1(1,1);
memset
(f,0,
sizeof
f); dfs2(1);
//build_tree(root,1,n);
for
(
int
i=1;i<=n-1;i++) tadd(ord[i],ord[i+1]);
qury(root,1,n,a[root].tag);
for
(
int
i=2;i<=n;i++) ans[ord[i]]--;
for
(
int
i=1;i<=n;i++)
printf
(
"%lld\n"
,ans[i]);
return
0;
}