自己乱搞了一个线段树维护dfs序,结果卡着内存过了。
dfs序维护的是子节点和父节点的关系,并不是路径上的关系。
然而膜拜题解发现只要在倍增lca的时候打上标记就可以了。不会On求lca,先挖一个坑
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>#define md
#define ll long long
#define inf (int) 1e9
#define eps 1e-8
#define N 600010
#define M 4*N
using namespace std;
struct yts { int x,t,ne;} e[2*N];
int left[N],right[N],opt[N],v[N],a[N],fa[N][25],dep[N];
int cheng[M],ad[M],dt[M];
int dfs_cnt=0,num=0,n;
void put(int x,int y)
{
num++; e[num].x=x; e[num].t=y;
e[num].ne=v[x]; v[x]=num;
}
void dfs(int x)
{
left[x]=++dfs_cnt; opt[dfs_cnt]=1;
for (int i=v[x];i;i=e[i].ne)
{
int y=e[i].t;
if (!left[y])
{
fa[y][0]=x; dep[y]=dep[x]+1;
dfs(y);
}
}
right[x]=++dfs_cnt; opt[dfs_cnt]=-1;
}
void build(int i,int l,int r)
{
cheng[i]=ad[i]=0;
if (l==r) { dt[i]=opt[l]; return;}
int mid=(l+r)>>1;
build(2*i,l,mid); build(2*i+1,mid+1,r);
dt[i]=dt[2*i]+dt[2*i+1];
}
void release(int i)
{
int l=2*i,r=2*i+1;
if (ad[i]!=0)
{
ad[l]+=ad[i]; ad[r]+=ad[i];
cheng[l]+=ad[i]; cheng[r]+=ad[i];
ad[i]=0;
}
}
void modify(int i,int l,int r,int d,int ln,int rn)
{
if (l<=ln&&rn<=r) { ad[i]+=d; cheng[i]+=d; return;}
release(i);
int mid=(ln+rn)>>1;
if(l<=mid) modify(2*i,l,r,d,ln,mid);
if (mid+1<=r) modify(2*i+1,l,r,d,mid+1,rn);
}
int query(int i,int x,int ln,int rn)
{
if (ln==rn) return cheng[i]*dt[i];
release(i);
int mid=(ln+rn)>>1;
if (x<=mid) return query(2*i,x,ln,mid); else return query(2*i+1,x,mid+1,rn);
}
void build_lca()
{
for (int j=1;j<=20;j++)
for (int i=1;i<=n;i++)
{
if (fa[i][j-1]) fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
int lca(int x,int y)
{
if (dep[x]<dep[y]) swap(x,y);
int t=dep[x]-dep[y];
for (int i=20;i>=0;i--) if (t&(1<<i)) x=fa[x][i];
if (x==y) return x;
for (int i=20;i>=0;i--)
if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
put(x,y); put(y,x);
}
dep[1]=1; dfs(1); build_lca();
//for (int i=1;i<=n;i++) printf("lr %d %d\n",left[i],right[i]);
build(1,1,dfs_cnt);
for (int i=2;i<=n;i++)
{
int x=a[i-1],y=a[i];
int z=lca(x,y);
if (z!=x&&z!=y) { modify(1,left[z],left[x],1,1,dfs_cnt); modify(1,left[z],left[y],1,1,dfs_cnt); modify(1,left[z],left[z],-1,1,dfs_cnt);}
else
{
if (left[x]>left[y]) swap(x,y);
modify(1,left[x],left[y],1,1,dfs_cnt);
}
//printf("mo: %d %d\n",x,y);
}
for (int i=1;i<=n;i++)
{
int ans=query(1,left[i],1,dfs_cnt)+query(1,right[i],1,dfs_cnt);
if (a[1]==i) printf("%d\n",ans); else printf("%d\n",ans-1);
}
return 0;
}