[BZOJ3631][JLOI2014]松鼠的新家(树链剖分)

时间:2023-11-15 12:04:02

[BZOJ3631]

树剖模板题了,

Code

#include <cstdio>
#include <algorithm>
#define MID int mid=(l+r)>>1,ls=id<<1,rs=id<<1|1
#define N 300010
using namespace std; struct info{int to,nex;}e[N*2];
int n,A[N],tot,head[N],tag[N*4],Ans[N];
int dep[N],fa[N],sz[N],son[N];
int cnt,tp[N],rk[N],tid[N]; inline int read(){
int x=0,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();}
return x*f;
} inline void Link(int u,int v){
e[++tot].nex=head[u];e[tot].to=v;head[u]=tot;
} inline void pushdown(int l,int r,int id){
MID;
tag[ls]+=tag[id];
tag[rs]+=tag[id];
tag[id]=0;
} void update(int l,int r,int id,int L,int R){
if(L<=l&&r<=R){
tag[id]++;
return;
}
MID;
if(tag[id]) pushdown(l,r,id);
if(L<=mid) update(l,mid,ls,L,R);
if(R>mid) update(mid+1,r,rs,L,R);
} void query(int l,int r,int id){
if(l==r){Ans[rk[l]]=tag[id];return;}
if(tag[id]) pushdown(l,r,id);
MID;
if(l<=mid) query(l,mid,ls);
if(r>mid) query(mid+1,r,rs);
} void dfs(int u,int pre){
sz[u]=1;
for(int i=head[u],mx=0;i;i=e[i].nex){
int v=e[i].to;
if(v==pre) continue;
dep[v]=dep[u]+1;
fa[v]=u;
dfs(v,u);
sz[u]+=sz[v];
if(sz[v]>mx) son[u]=v,mx=sz[v];
}
} void dddfs(int u,int top){
tp[u]=top;
tid[u]=++cnt;
rk[cnt]=u;
if(!son[u]) return; dddfs(son[u],top);
for(int i=head[u];i;i=e[i].nex){
int v=e[i].to;
if(v!=son[u]&&v!=fa[u]) dddfs(v,v);
}
} inline void updRange(int u,int v){
while(tp[u]!=tp[v]){
if(dep[tp[u]]<dep[tp[v]]) swap(u,v);
update(1,n,1,tid[tp[u]],tid[u]);
u=fa[tp[u]];
}
if(dep[u]>dep[v]) swap(u,v);
update(1,n,1,tid[u],tid[v]);
} inline void Init(){
n=read();
for(int i=1;i<=n;A[i++]=read());
for(int i=1;i<n;++i){
int u=read(),v=read();
Link(u,v),Link(v,u);
}
dfs(1,0);
dddfs(1,1);
} inline void solve(){
for(int i=1;i<n;++i) updRange(A[i],A[i+1]);
query(1,n,1);
for(int i=2;i<=n;++i) Ans[A[i]]--;
for(int i=1;i<=n;printf("%d\n",Ans[i++]));
} int main(){Init();solve();}