简单的树链剖分
主要是为了复习
利用线段树维护区间加1就好了
// ConsoleApplication5.cpp: 定义控制台应用程序的入口点。
//
//#include "stdafx.h"
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define lc (p<<1)
#define rc (p<<1|1)
using namespace std;
inline void read(int &x){
x=0;
int f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-'){
f=-1;
}
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
x*=f;
}
const int N = 1e6;
struct Front_star {
int u, v, nxt;
}e[N*4];
int first[N] = {};
int cnt = 1;
void add(int u, int v) {
cnt++;
e[cnt].u = u;
e[cnt].v = v;
e[cnt].nxt = first[u];
first[u] = cnt;
}
//
int dep[N] = {};
int siz[N] = {};
int son[N] = {};
int fa[N] = {};
int top[N] = {};
int tree[N] = {};
int pre[N] = {};
int tot = 0;
void dfs1(int x, int fat, int depth) {
fa[x] = fat;
dep[x] = depth;
siz[x] = 1;
for (int i = first[x]; i; i = e[i].nxt) {
int v = e[i].v;
if(v==fat)continue;
dfs1(v, x, depth + 1);
if (!son[x] || siz[son[x]] < siz[v]) {
son[x] = v;
}
}
}
void dfs2(int x, int tp) {
tree[x]=++tot;
pre[tp]=x;
top[x]=tp;
if(!son[x])return;
dfs2(son[x],tp);
for(int i=first[x];i;i=e[i].nxt){
int v=e[i].v;
if(v==fa[x])continue;
if(v==son[x])continue;
dfs2(v,v);
}
}
//
struct Segment_Tree{
int sum,lson,rson,lazy;
}T[N*4];
inline void PushUp(int p){
T[p].sum=T[lc].sum+T[rc].sum;
}
inline void PushDown(int p){
if(T[p].lazy){
// cout<<p<<" down"<<lc<<" "<<rc<<'\n';
T[lc].sum+=(T[lc].rson-T[lc].lson+1)*T[p].lazy;
T[rc].sum+=(T[rc].rson-T[rc].lson+1)*T[p].lazy;
T[lc].lazy+=T[p].lazy;
T[rc].lazy+=T[p].lazy;
T[p].lazy=0;
}
}
void build(int p,int l,int r){
T[p].lson=l;
T[p].rson=r;
if(l==r){
T[p].sum=0;
return;
}
int mid=(l+r)/2;
build(lc,l,mid);
build(rc,mid+1,r);
PushUp(p);
}
inline void update(int p,int l,int r,int val){
if(l<=T[p].lson&&T[p].rson<=r){
// cout<<"p= "<<p<<'\n';
T[p].sum+=(T[p].rson-T[p].lson+1)*val;
T[p].lazy+=val;
return;
}
PushDown(p);
int mid=(T[p].lson+T[p].rson)/2;
if(l<=mid)update(lc,l,r,val);
if(mid<r) update(rc,l,r,val);
PushUp(p);
}
inline int Query(int p,int l,int r){
// cout<<p<<" "<<T[p].lson<<" "<<T[p].rson<<'\n';
if(l<=T[p].lson&&T[p].rson<=r){
return T[p].sum;
}
PushDown(p);
int mid=(T[p].lson+T[p].rson)/2;
int ret=0;
if(l<=mid)ret+=Query(lc,l,r);
if(r>mid) ret+=Query(rc,l,r);
return ret;
}
int Up(int x,int y,int val){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]){
swap(x,y);
}
// cout<<"Up "<<top[x]<<" "<<x<<'\n';
update(1,tree[top[x]],tree[x],val);
x=fa[top[x]];
}
if(dep[x]>dep[y]){
swap(x,y);
}
// cout<<"Up "<<x<<" "<<y<<'\n';
update(1,tree[x],tree[y],val);
}
int n;
int a[N]={};
int main(){
// freopen("P3258.in","r",stdin);
// scanf("%d",&n);
read(n);
// cout<<n;
for(int i=1;i<=n;i++){
read(a[i]);
// scanf("%d",&a[i]);
}
for(int i=1;i<n;i++){
int u,v;
read(u);
read(v);
// scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs1(1,0,1);
// cout<<"------"<<'\n';
dfs2(1,1);
build(1,1,n);
// Up(a[1],a[2],1);
// cout<<Query(1,tree[4],tree[4])<<'\n';
// cout<<T[15].lson<<" "<<T[15].rson<<'\n';
for(int i=1;i<n;i++){
Up(a[i],a[i+1],1);
Up(a[i],a[i],-1);
// cout<<Query(1,tree[a[i]],tree[a[i]])<<'\n';
}
for(int i=1;i<=n;i++){
int ans=Query(1,tree[i],tree[i]);
if(a[1]==i)ans++;
if(a[n]==i)ans--;
cout<<ans<<'\n';
}
return 0;
}