易错点:
- 需要使用栈模拟递归
- 不开O2无法通过
// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
#include<stack>
using namespace std;
const int MAXN=1000010,MAXM=1000010;
struct Node{
int ls,rs,lazy;
long long sum;
}tr[MAXN];
int nodeCnt=0;
void insert(int &now,int l,int r,int ll,int rr,int x){
if(!now)now=++nodeCnt;
int b=min(r,rr)-max(l,ll)+1;
tr[now].sum+=x*b;
if(ll<=l&&rr>=r){
tr[now].lazy+=x;
return;
}
int mid=(l+r)>>1;
if(ll<=mid)insert(tr[now].ls,l,mid,ll,rr,x);
if(rr>mid)insert(tr[now].rs,mid+1,r,ll,rr,x);
}
long long query(int now,int l,int r,int ll,int rr){
if(ll<=l&&rr>=r)return tr[now].sum;
int mid=(l+r)>>1;
if(tr[now].lazy){
if(!tr[now].ls)tr[now].ls=++nodeCnt;
tr[tr[now].ls].lazy+=tr[now].lazy;
tr[tr[now].ls].sum+=tr[now].lazy*(mid-l+1);
if(!tr[now].rs)tr[now].rs=++nodeCnt;
tr[tr[now].rs].lazy+=tr[now].lazy;
tr[tr[now].rs].sum+=tr[now].lazy*(r-mid);
tr[now].lazy=0;
}
long long ans=0;
if(ll<=mid)ans+=query(tr[now].ls,l,mid,ll,rr);
if(rr>mid)ans+=query(tr[now].rs,mid+1,r,ll,rr);
return ans;
}
struct Edge{
int from,to,nxt;
}e[MAXM];
int head[MAXN],edgeCnt=1;
void addEdge(int u,int v){
e[++edgeCnt].from=u;
e[edgeCnt].to=v;
e[edgeCnt].nxt=head[u];
head[u]=edgeCnt;
}
int dep[MAXN],fa[MAXN],son[MAXN],siz[MAXN];
struct dfs_Node{
int point;
int type;
};
void dfs1(int x){
stack<dfs_Node> s;
s.push(dfs_Node{x,1});
while(!s.empty()){
dfs_Node nowNode=s.top();s.pop();
int type=nowNode.type,nowPoint=nowNode.point;
if(type==1){
dep[nowPoint]=dep[fa[nowPoint]]+1;
siz[nowPoint]=1;
s.push(dfs_Node{nowPoint,2});
for(int i=head[nowPoint];i;i=e[i].nxt){
int nowV=e[i].to;
if(!dep[nowV]){
fa[nowV]=nowPoint;
s.push(dfs_Node{nowV,1});
}
}
}else if(type==2){
for(int i=head[nowPoint];i;i=e[i].nxt){
int nowV=e[i].to;
if(nowV==fa[nowPoint])continue;
siz[nowPoint]+=siz[nowV];
if(siz[nowV]>siz[son[nowPoint]])son[nowPoint]=nowV;
}
}
}
}
int id[MAXN],idCnt=0;
int top[MAXN],root=0;
void dfs2(int x){
stack<dfs_Node> s;
s.push(dfs_Node{x,0});
while(!s.empty()){
dfs_Node nowNode=s.top();s.pop();
int nowPoint=nowNode.point,nowType=nowNode.type;
if(nowType==0){
id[nowPoint]=++idCnt;
s.push(dfs_Node{nowPoint,1});
if(nowPoint==son[fa[nowPoint]])top[nowPoint]=top[fa[nowPoint]];
else top[nowPoint]=nowPoint;
if(son[nowPoint])s.push(dfs_Node{son[nowPoint],0});
}else if(nowType==1){
for(int i=head[nowPoint];i;i=e[i].nxt){
int nowV=e[i].to;
if(!id[nowV])s.push(dfs_Node{nowV,0});
}
}
}
}
void modify(int u,int v,int x){
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]])swap(u,v);
insert(root,1,MAXN,id[top[v]],id[v],x);
v=fa[top[v]];
}
insert(root,1,MAXN,min(id[u],id[v]),max(id[u],id[v]),x);
}
long long sum(int u,int v){
long long ans=0;
while(top[u]!=top[v]){
if(dep[top[u]]>dep[top[v]])swap(u,v);
ans+=query(root,1,MAXN,id[top[v]],id[v]);
v=fa[top[v]];
}
ans+=query(root,1,MAXN,min(id[u],id[v]),max(id[u],id[v]));
return ans;
}
int read(){
char c;int num,f=1;
while(c=getchar(),!isdigit(c))if(c=='-')f=-1;num=c-'0';
while(c=getchar(), isdigit(c))num=num*10+c-'0';
return f*num;
}
int a[MAXN];
int main(){
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout);
int n;
n=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<=n-1;i++){
int x,y;
x=read();y=read();
addEdge(x,y);
addEdge(y,x);
}
dfs1(1);
dfs2(1);
for(int i=1;i<=n-1;i++){
modify(a[i],a[i+1],1);
modify(a[i+1],a[i+1],-1);
}
for(int i=1;i<=n;i++){
printf("%lld\n",query(root,1,MAXN,id[i],id[i]));
}
return 0;
}